home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / daocore.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-16  |  132.3 KB  |  5,902 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_DB_SEG
  14. #pragma code_seg(AFX_DB_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #pragma comment(lib, "ole32.lib")
  23.  
  24. #define new DEBUG_NEW
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // Maintain DAODBEngine object
  28.  
  29. _AFX_DAO_STATE::_AFX_DAO_STATE()
  30. {
  31.     m_pDAODBEngine = NULL;
  32.     m_bOleInitialized = FALSE;
  33. }
  34.  
  35. _AFX_DAO_STATE::~_AFX_DAO_STATE()
  36. {
  37.     // these ASSERTs can trip when:
  38.     // ... there any outstanding workspsace objects
  39.     ASSERT(m_mapWorkspaces.IsEmpty());
  40.  
  41.     // ... you've not shut down with a call AfxDaoTerm()
  42.     ASSERT(m_pDAODBEngine == NULL);
  43.  
  44.     // ... OLE wasn't correctly shut down
  45.     ASSERT(!m_bOleInitialized);
  46. }
  47.  
  48. //////////////////////////////////////////////////////////////////////////
  49. // Helpers
  50.  
  51. // Index function return value
  52. #define AFX_DAO_DATA_NOT_FOUND                  (-1L)
  53.  
  54. #define AFX_DAO_FETCH_PRIMARY_PROPERTIES \
  55.     (AFX_DAO_PRIMARY_INFO | AFX_DAO_SECONDARY_INFO | AFX_DAO_ALL_INFO)
  56. #define AFX_DAO_FETCH_SECONDARY_PROPERTIES \
  57.     (AFX_DAO_SECONDARY_INFO | AFX_DAO_ALL_INFO)
  58. #define AFX_DAO_FETCH_ALL_PROPERTIES \
  59.     AFX_DAO_ALL_INFO
  60.  
  61. // Info helpers
  62. void AFX_CDECL AfxGetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo,
  63.     DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);
  64. void AFX_CDECL AfxSetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo);
  65. void AFX_CDECL AfxGetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo,
  66.     DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);
  67. void AFX_CDECL AfxSetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo);
  68. void AFX_CDECL AfxGetIndexFields(DAOIndex* pDAOIndex,
  69.     DAOIndexFields** ppDAOIndexFields);
  70. void AFX_CDECL AfxGetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo);
  71. void AFX_CDECL AfxSetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo);
  72. void AFX_CDECL AfxGetDefaultValue(DAOField* pDAOField, CString& strDefaultValue);
  73. void AFX_CDECL AfxSetDefaultValue(DAOField* pDAOField, CString& strDefaultValue);
  74.  
  75. // GetRows helper
  76. void AFX_CDECL ThrowGetRowsDaoException(SCODE scode);
  77.  
  78. // _AFX_DAO_STATE helper
  79. _AFX_DAO_STATE* AFX_CDECL AfxGetDaoState();
  80.  
  81. //////////////////////////////////////////////////////////////////////////
  82. // Global data
  83.  
  84. AFX_STATIC_DATA const TCHAR _afxParameters2[] = _T("PARAMETERS ");
  85. AFX_STATIC_DATA const TCHAR _afxSelect2[] = _T("SELECT ");
  86. AFX_STATIC_DATA const TCHAR _afxFrom2[] = _T(" FROM ");
  87. AFX_STATIC_DATA const TCHAR _afxWhere2[] = _T(" WHERE ");
  88. AFX_STATIC_DATA const TCHAR _afxOrderBy2[] = _T(" ORDER BY ");
  89. AFX_STATIC_DATA const TCHAR _afxTransform2[] = _T("TRANSFORM ");
  90. AFX_STATIC_DATA const TCHAR _afxTable2[] = _T("TABLE ");
  91.  
  92. // Need a static VARIANT for optional DAO parameters
  93. AFX_STATIC_DATA VARIANT _afxOptionalVariant = { VT_ERROR, 0, 0, 0, DISP_E_PARAMNOTFOUND };
  94.  
  95. // Need a static VARIANT for NULL DAO parameters
  96. AFX_STATIC_DATA VARIANT _afxNullVariant = { VT_NULL, 0, 0, 0, 0 };
  97.  
  98. //////////////////////////////////////////////////////////////////////////
  99. // Logging helpers
  100.  
  101. void AFXAPI AfxDaoCheck(SCODE scode, LPCSTR lpszDaoCall,
  102.     LPCSTR lpszFile, int nLine, int nError, BOOL bMemOnly)
  103. {
  104.     UNUSED(lpszDaoCall);
  105.     UNUSED(lpszFile);
  106.     UNUSED(nLine);
  107.  
  108.     if (FAILED(scode))
  109.     {
  110. #ifdef _DEBUG
  111.         if (afxTraceFlags & traceDatabase)
  112.         {
  113.             TRACE0("\nDAO Call Failed.");
  114.             TRACE1("\n\t%hs", lpszDaoCall);
  115.             TRACE2("\n\tIn file %hs on line %d", lpszFile, nLine);
  116.             TRACE1("\n\tscode = %X\n", scode);
  117.         }
  118. #endif
  119.         if (scode == E_OUTOFMEMORY)
  120.             AfxThrowMemoryException();
  121.         else if (!bMemOnly)
  122.             AfxThrowDaoException(nError, scode);
  123.     }
  124. }
  125.  
  126. #ifdef _DEBUG
  127. void AFXAPI AfxDaoTrace(SCODE scode, LPCSTR lpszDaoCall,
  128.     LPCSTR lpszFile, int nLine)
  129. {
  130.     if (FAILED(scode))
  131.     {
  132.         if (afxTraceFlags & traceDatabase)
  133.         {
  134.             TRACE0("\nDAO Call Failed.\n\t");
  135.             TRACE1("\n%hs", lpszDaoCall);
  136.             TRACE2("\nIn file %hs on line %d\n", lpszFile, nLine);
  137.             TRACE1("scode = %X\n", scode);
  138.         }
  139.     }
  140. }
  141. #endif // _DEBUG
  142.  
  143. //////////////////////////////////////////////////////////////////////////
  144. // Info structure diagnostics
  145.  
  146. #ifdef _DEBUG
  147. void CDaoErrorInfo::Dump(CDumpContext& dc) const
  148. {
  149.     dc << "a CDaoErrorInfo at " << (void*)this;
  150.  
  151.     dc << "\nm_lErrorCode = " << m_lErrorCode;
  152.     dc << "\nm_strSource = " << m_strSource;
  153.     dc << "\nm_strDescription = " << m_strDescription;
  154.     dc << "\nm_strHelpFile = " << m_strHelpFile;
  155.     dc << "\nm_lHelpContext = " << m_lHelpContext;
  156.  
  157.     dc << "\n";
  158. }
  159. #endif // _DEBUG
  160.  
  161. #ifdef _DEBUG
  162. void CDaoWorkspaceInfo::Dump(CDumpContext& dc) const
  163. {
  164.     dc << "a CDaoWorkspaceInfo at " << (void*)this;
  165.  
  166.     dc << "\nm_strName = " << m_strName;
  167.     dc << "\nm_strUserName = " << m_strUserName;
  168.     dc << "\nb = m_bIsolateODBCTrans" << m_bIsolateODBCTrans;
  169.  
  170.     dc << "\n";
  171. }
  172. #endif // _DEBUG
  173.  
  174. #ifdef _DEBUG
  175. void CDaoDatabaseInfo::Dump(CDumpContext& dc) const
  176. {
  177.     dc << "a CDaoDatabaseInfo at " << (void*)this;
  178.  
  179.     dc << "\nm_strName = " << m_strName;
  180.     dc << "\nm_bUpdatable = " << m_bUpdatable;
  181.     dc << "\nm_bTransactions = " << m_bTransactions;
  182.     dc << "\nm_strVersion = " << m_strVersion;
  183.     dc << "\nm_lCollatingOrder = " << m_lCollatingOrder;
  184.     dc << "\nm_nQueryTimeout = " << m_nQueryTimeout;
  185.     dc << "\nm_strConnect = " << m_strConnect;
  186.  
  187.     dc << "\n";
  188. }
  189. #endif // _DEBUG
  190.  
  191. #ifdef _DEBUG
  192. void CDaoTableDefInfo::Dump(CDumpContext& dc) const
  193. {
  194.     dc << "a CDaoTableDefInfo at " << (void*)this;
  195.  
  196.     dc << "\nm_strName = " << m_strName;
  197.     dc << "\nm_bUpdatable = " << m_bUpdatable;
  198.     dc << "\nm_lAttributes = " << m_lAttributes;
  199.     dc << "\nm_dateDateCreated = " << m_dateCreated;
  200.     dc << "\nm_dateLastUpdated = " << m_dateLastUpdated;
  201.     dc << "\nm_strSrcTableName = " << m_strSrcTableName;
  202.     dc << "\nm_strConnect = " << m_strConnect;
  203.     dc << "\nm_strValidationRule = " << m_strValidationRule;
  204.     dc << "\nm_strValidationText = " << m_strValidationText;
  205.     dc << "\nm_lRecordCount = " << m_lRecordCount;
  206.  
  207.     dc << "\n";
  208. }
  209. #endif // _DEBUG
  210.  
  211. #ifdef _DEBUG
  212. void CDaoFieldInfo::Dump(CDumpContext& dc) const
  213. {
  214.     dc << "a CDaoFieldInfo at " << (void*)this;
  215.  
  216.     dc << "\nm_strName = " << m_strName;
  217.     dc << "\nm_nType = " << m_nType;
  218.     dc << "\nm_lSize = " << m_lSize;
  219.     dc << "\nm_lAttributes = " << m_lAttributes;
  220.     dc << "\nm_nOrdinalPosition = " << m_nOrdinalPosition;
  221.     dc << "\nm_bRequired = " << m_bRequired;
  222.     dc << "\nm_bAllowZeroLength = " << m_bAllowZeroLength;
  223.     dc << "\nm_lCollatingOrder = " << m_lCollatingOrder;
  224.     dc << "\nm_strForeignName = " << m_strForeignName;
  225.     dc << "\nm_strSourceField = " << m_strSourceField;
  226.     dc << "\nm_strSourceTable = " << m_strSourceTable;
  227.     dc << "\nm_strValidationRule = " << m_strValidationRule;
  228.     dc << "\nm_strValidationText = " << m_strValidationText;
  229.     dc << "\nm_strDefaultValue = " << m_strDefaultValue;
  230.  
  231.     dc << "\n";
  232. }
  233. #endif // _DEBUG
  234.  
  235. #ifdef _DEBUG
  236. void CDaoIndexFieldInfo::Dump(CDumpContext& dc) const
  237. {
  238.     dc << " a CDaoIndexFieldInfo at " << (void*)this;
  239.  
  240.     dc << "\nm_strName = " << m_strName;
  241.     dc << "\nm_bDescending = " << m_bDescending;
  242. }
  243. #endif
  244.  
  245. CDaoIndexInfo::CDaoIndexInfo()
  246. {
  247.     m_pFieldInfos = NULL;
  248.     m_nFields = 0;
  249.     m_bCleanupFieldInfo = FALSE;
  250. }
  251.  
  252. CDaoIndexInfo::~CDaoIndexInfo()
  253. {
  254.     if (m_bCleanupFieldInfo && m_pFieldInfos != NULL)
  255.     {
  256.         delete[] m_pFieldInfos;
  257.         m_pFieldInfos = NULL;
  258.     }
  259. }
  260.  
  261. #ifdef _DEBUG
  262. void CDaoIndexInfo::Dump(CDumpContext& dc) const
  263. {
  264.     dc << "a CDaoIndexInfo at " << (void*)this;
  265.  
  266.     dc << "\nm_strName = " << m_strName;
  267.     dc << "\nm_nFields = " << m_nFields;
  268.  
  269.     for (int nIndex = 0; nIndex < m_nFields; nIndex++)
  270.         m_pFieldInfos[nIndex].Dump(dc);
  271.  
  272.     dc << "\nm_bPrimary = " << m_bPrimary;
  273.     dc << "\nm_bUnique = " << m_bUnique;
  274.     dc << "\nm_bClustered = " << m_bClustered;
  275.     dc << "\nm_bIgnoreNulls = " << m_bIgnoreNulls;
  276.     dc << "\nm_bRequired = " << m_bRequired;
  277.     dc << "\nm_bForeign = " << m_bForeign;
  278.     dc << "\nm_lDistinctCount = " << m_lDistinctCount;
  279.  
  280.     dc << "\n";
  281. }
  282. #endif // _DEBUG
  283.  
  284. #ifdef _DEBUG
  285. void CDaoRelationFieldInfo::Dump(CDumpContext& dc) const
  286. {
  287.     dc << " a CDaoRelationFieldInfo at " << (void*)this;
  288.  
  289.     dc << "\nm_strName = " << m_strName;
  290.     dc << "\nm_strForeignName = " << m_strForeignName;
  291. }
  292. #endif
  293.  
  294. CDaoRelationInfo::CDaoRelationInfo()
  295. {
  296.     m_pFieldInfos = NULL;
  297.     m_nFields = 0;
  298.     m_bCleanupFieldInfo = FALSE;
  299. }
  300.  
  301. CDaoRelationInfo::~CDaoRelationInfo()
  302. {
  303.     if (m_bCleanupFieldInfo && m_pFieldInfos != NULL)
  304.     {
  305.         delete[] m_pFieldInfos;
  306.         m_pFieldInfos = NULL;
  307.     }
  308. }
  309.  
  310. #ifdef _DEBUG
  311. void CDaoRelationInfo::Dump(CDumpContext& dc) const
  312. {
  313.     dc << "a CDaoRelationInfo at " << (void*)this;
  314.  
  315.     dc << "\nm_strName = " << m_strName;
  316.     dc << "\nm_strTable = " << m_strTable;
  317.     dc << "\nm_strForeignTable = " << m_strForeignTable;
  318.     dc << "\nm_lAttributes = " << m_lAttributes;
  319.     dc << "\nm_nFields = " << m_nFields;
  320.  
  321.     for (int nIndex = 0; nIndex < m_nFields; nIndex++)
  322.         m_pFieldInfos[nIndex].Dump(dc);
  323.  
  324.     dc << "\n";
  325. }
  326. #endif // _DEBUG
  327.  
  328. #ifdef _DEBUG
  329. void CDaoQueryDefInfo::Dump(CDumpContext& dc) const
  330. {
  331.     dc << "a CDaoQueryDefInfo at " << (void*)this;
  332.  
  333.     dc << "\nm_strName = " << m_strName;
  334.     dc << "\nm_nType = " << m_nType;
  335.     dc << "\nm_dateCreated = " << m_dateCreated;
  336.     dc << "\nm_dateLastUpdated = " << m_dateLastUpdated;
  337.     dc << "\nm_bUpdatable = " << m_bUpdatable;
  338.     dc << "\nm_bReturnsRecords = " << m_bReturnsRecords;
  339.     dc << "\nm_strSQL = " << m_strSQL;
  340.     dc << "\nm_strConnect = " << m_strConnect;
  341.     dc << "\nm_nODBCTimeout = " << m_nODBCTimeout;
  342.  
  343.     dc << "\n";
  344. }
  345. #endif // _DEBUG
  346.  
  347. #ifdef _DEBUG
  348. void CDaoParameterInfo::Dump(CDumpContext& dc) const
  349. {
  350.     dc << "a CDaoParameterInfo at " << (void*)this;
  351.  
  352.     dc << "\nm_strName = " << m_strName;
  353.     dc << "\nm_nType = " << m_nType;
  354.     dc << "\nm_varValue = " << m_varValue;
  355.  
  356.     dc << "\n";
  357. }
  358. #endif // _DEBUG
  359.  
  360. //////////////////////////////////////////////////////////////////////////
  361. // CDaoException
  362. IMPLEMENT_DYNAMIC(CDaoException, CException)
  363.  
  364. CDaoException::CDaoException()
  365. {
  366.     m_pDAOError = NULL;
  367.     m_pDAOErrors = NULL;
  368.     m_pErrorInfo = NULL;
  369. }
  370.  
  371. CDaoException::~CDaoException()
  372. {
  373.     delete m_pErrorInfo;
  374.     m_pErrorInfo = NULL;
  375.  
  376.     if (m_pDAOErrors != NULL)
  377.     {
  378.         m_pDAOErrors->Release();
  379.         m_pDAOErrors = NULL;
  380.     }
  381.  
  382.     if (m_pDAOError != NULL)
  383.     {
  384.         m_pDAOError->Release();
  385.         m_pDAOError = NULL;
  386.     }
  387. }
  388.  
  389. // Operations
  390. short CDaoException::GetErrorCount()
  391. {
  392.     short nErrors = 1;
  393.  
  394.     if (m_pDAOErrors == NULL)
  395.         InitErrorsCollection();
  396.  
  397.     if (m_nAfxDaoError != AFX_DAO_ERROR_ENGINE_INITIALIZATION)
  398.         DAO_CHECK_MEM(m_pDAOErrors->get_Count(&nErrors));
  399.  
  400.     return nErrors;
  401. }
  402.  
  403. void CDaoException::GetErrorInfo(int nIndex)
  404. {
  405.     ASSERT(m_pDAOError == NULL);
  406.  
  407.     if (m_pDAOErrors == NULL)
  408.         InitErrorsCollection();
  409.  
  410.     if (m_nAfxDaoError != AFX_DAO_ERROR_ENGINE_INITIALIZATION)
  411.     {
  412.         // Get DAOError object and fill in error info struct
  413.         DAO_CHECK_MEM(m_pDAOErrors->get_Item(
  414.             COleVariant((long)nIndex), &m_pDAOError));
  415.  
  416.         FillErrorInfo();
  417.  
  418.         // Clean up
  419.         m_pDAOError->Release();
  420.         m_pDAOError = NULL;
  421.     }
  422. }
  423.  
  424. BOOL CDaoException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
  425.     PUINT pnHelpContext)
  426. {
  427.     ASSERT(lpszError != NULL && AfxIsValidString(lpszError, nMaxError));
  428.  
  429.     BOOL bRetCode = FALSE;
  430.  
  431.     if (m_pErrorInfo != NULL)
  432.     {
  433.         // DAO help context is not a UINT!
  434.         //  According to DAO it is positive and should be less 10,000,000
  435.         if (pnHelpContext != NULL)
  436.             *pnHelpContext = (UINT) m_pErrorInfo->m_lHelpContext;
  437.  
  438.         lstrcpyn(lpszError, m_pErrorInfo->m_strDescription, nMaxError-1);
  439.         lpszError[nMaxError-1] = '\0';
  440.         bRetCode = TRUE;
  441.     }
  442.     else
  443.     {
  444.         // Must be MFC DAO class internal error, get error string
  445.         CString strError;
  446.         if (strError.LoadString(
  447.             AFX_IDP_DAO_FIRST + (m_nAfxDaoError - AFX_DAO_ERROR_MIN)))
  448.         {
  449.             lstrcpyn(lpszError, strError, nMaxError-1);
  450.             bRetCode = TRUE;
  451.         }
  452.         else
  453.             ASSERT(FALSE);  // Couldn't get resource.
  454.     }
  455.     return bRetCode;
  456. }
  457.  
  458. // Implementation
  459. void CDaoException::InitErrorsCollection()
  460. {
  461.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  462.  
  463.     // Engine not initialized!
  464.     if (pDaoState->m_pDAODBEngine == NULL)
  465.         m_nAfxDaoError = AFX_DAO_ERROR_ENGINE_INITIALIZATION;
  466.     else
  467.         DAO_CHECK_MEM(pDaoState->m_pDAODBEngine->get_Errors(
  468.             &m_pDAOErrors));
  469. }
  470.  
  471. void CDaoException::FillErrorInfo()
  472. {
  473.     ASSERT(m_pDAOError != NULL);
  474.     // Allocate the error info structure if necessary
  475.     if (m_pErrorInfo == NULL)
  476.         m_pErrorInfo = new CDaoErrorInfo;
  477.  
  478.     COleVariant var;
  479.  
  480.     DAO_CHECK_MEM(m_pDAOError->get_Number(
  481.         &m_pErrorInfo->m_lErrorCode));
  482.  
  483.     DAO_CHECK_MEM(m_pDAOError->get_Source(&V_BSTR(&var)));
  484.     var.vt = VT_BSTR;
  485.     m_pErrorInfo->m_strSource = V_BSTRT(&var);
  486.     var.Clear();
  487.  
  488.     DAO_CHECK_MEM(m_pDAOError->get_Description(&V_BSTR(&var)));
  489.     var.vt = VT_BSTR;
  490.     m_pErrorInfo->m_strDescription = V_BSTRT(&var);
  491.     var.Clear();
  492.  
  493.     DAO_CHECK_MEM(m_pDAOError->get_HelpFile(&V_BSTR(&var)));
  494.     var.vt = VT_BSTR;
  495.     m_pErrorInfo->m_strHelpFile = V_BSTRT(&var);
  496.     var.Clear();
  497.  
  498.     DAO_CHECK_MEM(m_pDAOError->get_HelpContext(
  499.         &m_pErrorInfo->m_lHelpContext));
  500. }
  501.  
  502. void AFXAPI AfxThrowDaoException(int nAfxDaoError, SCODE scode)
  503. {
  504.     CDaoException* pException;
  505.     pException = new CDaoException;
  506.  
  507.     pException->m_scode = scode;
  508.  
  509.     if (nAfxDaoError == NO_AFX_DAO_ERROR)
  510.     {
  511.         TRY
  512.         {
  513.             int nErrors = pException->GetErrorCount();
  514.             for (int nIndex = 0; nIndex < nErrors; nIndex++)
  515.             {
  516.                 pException->GetErrorInfo(nIndex);
  517. #ifdef _DEBUG
  518.                 if (afxTraceFlags & traceDatabase)
  519.                 {
  520.                     TRACE1("\nError Code = %d\n",
  521.                         pException->m_pErrorInfo->m_lErrorCode);
  522.                     TRACE1("Source = %s\n",
  523.                         (LPCTSTR)pException->m_pErrorInfo->m_strSource);
  524.                     TRACE1("Description = %s\n",
  525.                         (LPCTSTR)pException->m_pErrorInfo->m_strDescription);
  526.                 }
  527. #endif // _DEBUG
  528.             }
  529.         }
  530.         CATCH_ALL(e)
  531.         {
  532.             // No DAO error info
  533.             e->Delete();
  534.         }
  535.         END_CATCH_ALL
  536.     }
  537.     else
  538.         pException->m_nAfxDaoError = nAfxDaoError;
  539.  
  540.     THROW(pException);
  541. }
  542.  
  543.  
  544. //////////////////////////////////////////////////////////////////////////
  545. // CDaoWorkspace
  546. IMPLEMENT_DYNAMIC(CDaoWorkspace, CObject)
  547.  
  548. CDaoWorkspace::CDaoWorkspace()
  549. {
  550.     m_pDAOWorkspaces = NULL;
  551.     m_pDAOWorkspace = NULL;
  552.     m_pDAODatabases = NULL;
  553.  
  554.     m_bOpen = FALSE;
  555.     m_bNew = FALSE;
  556.     m_nStatus = 0;
  557. }
  558.  
  559. CDaoWorkspace::~CDaoWorkspace()
  560. {
  561.     if (IsOpen())
  562.     {
  563.         m_nStatus |= AFX_DAO_IMPLICIT_CLOSE;
  564.         Close();
  565.     }
  566.     else if (m_bNew)
  567.     {
  568.         // Remove the workspace from the AFX_DAO_STATE's map
  569.         _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  570.         pDaoState->m_mapWorkspaces.RemoveKey(this);
  571.     }
  572. }
  573.  
  574. void CDaoWorkspace::Create(LPCTSTR lpszName, LPCTSTR lpszUserName,
  575.     LPCTSTR lpszPassword)
  576. {
  577.     ASSERT_VALID(this);
  578.     ASSERT(!IsOpen());
  579.     ASSERT(lpszUserName != NULL);
  580.     ASSERT(lpszPassword != NULL);
  581.  
  582.     // Get the DAODBEngine interface and initialize if necessary
  583.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  584.     if (pDaoState->m_pDAODBEngine == NULL)
  585.         InitializeEngine();
  586.  
  587.     COleVariant varName(lpszName, VT_BSTRT);
  588.     COleVariant varUserName(lpszUserName, VT_BSTRT);
  589.     COleVariant varPassword(lpszPassword, VT_BSTRT);
  590.  
  591.     DAO_CHECK(pDaoState->m_pDAODBEngine->_30_CreateWorkspace(
  592.         V_BSTR(&varName), V_BSTR(&varUserName),
  593.         V_BSTR(&varPassword), &m_pDAOWorkspace));
  594.  
  595.     m_bNew = TRUE;
  596.  
  597.     // Add the workspace to map of Open/New CDaoWorkspaces
  598.     pDaoState->m_mapWorkspaces.SetAt(this, this);
  599. }
  600.  
  601. void CDaoWorkspace::Append()
  602. {
  603.     ASSERT_VALID(this);
  604.     ASSERT(m_bNew);
  605.     ASSERT(m_pDAOWorkspace != NULL);
  606.  
  607.     DAOWorkspaces* pDAOWorkspaces;
  608.  
  609.     // Get the DAODBEngine interface and initialize if necessary
  610.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  611.     if (pDaoState->m_pDAODBEngine == NULL)
  612.         InitializeEngine();
  613.  
  614.     DAO_CHECK(pDaoState->m_pDAODBEngine->get_Workspaces(&pDAOWorkspaces));
  615.  
  616.     TRY
  617.     {
  618.         DAO_CHECK(pDAOWorkspaces->Append(m_pDAOWorkspace));
  619.     }
  620.     CATCH_ALL(e)
  621.     {
  622.         pDAOWorkspaces->Release();
  623.         THROW_LAST();
  624.     }
  625.     END_CATCH_ALL
  626.  
  627.     pDAOWorkspaces->Release();
  628.  
  629.     m_bNew = FALSE;
  630.     m_bOpen = TRUE;
  631. }
  632.  
  633. void CDaoWorkspace::Open(LPCTSTR lpszWorkspaceName)
  634. {
  635.     ASSERT_VALID(this);
  636.     ASSERT(m_pDAOWorkspaces == NULL);
  637.     ASSERT(m_pDAOWorkspace == NULL);
  638.  
  639.     // Re-Opening is invalid.
  640.     if (IsOpen())
  641.     {
  642.         ASSERT(FALSE);
  643.         return;
  644.     }
  645.  
  646.     // Set the workspace name (or use 0 if opening default)
  647.     COleVariant var(lpszWorkspaceName, VT_BSTRT);
  648.     if (lpszWorkspaceName == NULL)
  649.     {
  650.         var = 0L;
  651.  
  652.         // Set status to prevent DAO Workspace Close call
  653.         m_nStatus |= AFX_DAO_DEFAULT_WS;
  654.     }
  655.  
  656.     // Get the DAODBEngine interface and initialize if necessary
  657.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  658.     if (pDaoState->m_pDAODBEngine == NULL)
  659.         InitializeEngine();
  660.  
  661.     // Get the workspace from the workspaces collection
  662.     DAO_CHECK(pDaoState->m_pDAODBEngine->get_Workspaces(
  663.         &m_pDAOWorkspaces));
  664.     DAO_CHECK(m_pDAOWorkspaces->get_Item(var, &m_pDAOWorkspace));
  665.  
  666.     m_bOpen = TRUE;
  667.     m_pDAOWorkspaces->Release();
  668.     m_pDAOWorkspaces = NULL;
  669.  
  670.     // Add the workspace to map of Open/New CDaoWorkspaces
  671.     pDaoState->m_mapWorkspaces.SetAt(this, this);
  672. }
  673.  
  674. void CDaoWorkspace::Close()
  675. {
  676.     ASSERT_VALID(this);
  677.  
  678.     if (m_pDAODatabases != NULL)
  679.     {
  680.         m_pDAODatabases->Release();
  681.         m_pDAODatabases = NULL;
  682.     }
  683.  
  684.     // Close any Open CDaoDatabases
  685.     void* pvKey;
  686.     void* pvObject;
  687.     POSITION pos = m_mapDatabases.GetStartPosition();
  688.     while (pos != NULL)
  689.     {
  690.         m_mapDatabases.GetNextAssoc(pos, pvKey, pvObject);
  691.         ((CDaoDatabase*)pvObject)->Close();
  692.     }
  693.     m_mapDatabases.RemoveAll();
  694.  
  695.     if (m_pDAOWorkspace != NULL)
  696.     {
  697.         // If implicit workspace or close, don't call DAO close.
  698.         // It will be automatically closed when ref count 0.
  699.         if (!(m_nStatus & (AFX_DAO_IMPLICIT_WS | AFX_DAO_IMPLICIT_CLOSE |
  700.             AFX_DAO_DEFAULT_WS)))
  701.         {
  702.             DAO_TRACE(m_pDAOWorkspace->Close());
  703.         }
  704.  
  705.         m_pDAOWorkspace->Release();
  706.         m_pDAOWorkspace = NULL;
  707.     }
  708.  
  709.     if (m_pDAOWorkspaces != NULL)
  710.     {
  711.         m_pDAOWorkspaces->Release();
  712.         m_pDAOWorkspaces = NULL;
  713.     }
  714.  
  715.     m_bOpen = FALSE;
  716.     m_bNew = FALSE;
  717.     m_nStatus &= ~AFX_DAO_DEFAULT_WS;
  718.  
  719.     // Remove the workspace from the AFX_DAO_STATE's map
  720.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  721.     pDaoState->m_mapWorkspaces.RemoveKey(this);
  722. }
  723.  
  724. CString PASCAL CDaoWorkspace::GetVersion()
  725. {
  726.     COleVariant var;
  727.  
  728.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  729.     if (pDaoState->m_pDAODBEngine == NULL)
  730.         InitializeEngine();
  731.  
  732.     DAO_CHECK(pDaoState->m_pDAODBEngine->get_Version(&V_BSTR(&var)));
  733.     var.vt = VT_BSTR;
  734.     return V_BSTRT(&var);
  735. }
  736.  
  737. CString PASCAL CDaoWorkspace::GetIniPath()
  738. {
  739.     COleVariant var;
  740.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  741.     if (pDaoState->m_pDAODBEngine == NULL)
  742.         InitializeEngine();
  743.  
  744.     DAO_CHECK(pDaoState->m_pDAODBEngine->get_IniPath(&V_BSTR(&var)));
  745.     var.vt = VT_BSTR;
  746.     return V_BSTRT(&var);
  747. }
  748.  
  749. void PASCAL CDaoWorkspace::SetIniPath(LPCTSTR lpszRegistrySubKey)
  750. {
  751.     COleVariant var(lpszRegistrySubKey, VT_BSTRT);
  752.  
  753.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  754.     if (pDaoState->m_pDAODBEngine == NULL)
  755.         InitializeEngine();
  756.  
  757.     DAO_CHECK(pDaoState->m_pDAODBEngine->put_IniPath(V_BSTR(&var)));
  758. }
  759.  
  760. void PASCAL CDaoWorkspace::SetDefaultUser(LPCTSTR lpszDefaultUser)
  761. {
  762.     COleVariant var(lpszDefaultUser, VT_BSTRT);
  763.  
  764.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  765.     if (pDaoState->m_pDAODBEngine == NULL)
  766.         InitializeEngine();
  767.  
  768.     DAO_CHECK(pDaoState->m_pDAODBEngine->put_DefaultUser(V_BSTR(&var)));
  769. }
  770.  
  771. void PASCAL CDaoWorkspace::SetDefaultPassword(LPCTSTR lpszPassword)
  772. {
  773.     COleVariant var(lpszPassword, VT_BSTRT);
  774.  
  775.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  776.     if (pDaoState->m_pDAODBEngine == NULL)
  777.         InitializeEngine();
  778.  
  779.     DAO_CHECK(pDaoState->m_pDAODBEngine->put_DefaultPassword(
  780.         V_BSTR(&var)));
  781. }
  782.  
  783. short PASCAL CDaoWorkspace::GetLoginTimeout()
  784. {
  785.     short nSeconds;
  786.  
  787.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  788.     if (pDaoState->m_pDAODBEngine == NULL)
  789.         InitializeEngine();
  790.  
  791.     DAO_CHECK(pDaoState->m_pDAODBEngine->get_LoginTimeout(&nSeconds));
  792.     return nSeconds;
  793. }
  794.  
  795. void PASCAL CDaoWorkspace::SetLoginTimeout(short nSeconds)
  796. {
  797.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  798.     if (pDaoState->m_pDAODBEngine == NULL)
  799.         InitializeEngine();
  800.  
  801.     DAO_CHECK(pDaoState->m_pDAODBEngine->put_LoginTimeout(nSeconds));
  802. }
  803.  
  804.  
  805. CString CDaoWorkspace::GetName()
  806. {
  807.     ASSERT_VALID(this);
  808.     ASSERT(m_pDAOWorkspace != NULL);
  809.  
  810.     COleVariant var;
  811.     DAO_CHECK(m_pDAOWorkspace->get_Name(&V_BSTR(&var)));
  812.     var.vt = VT_BSTR;
  813.     return V_BSTRT(&var);
  814. }
  815.  
  816. CString CDaoWorkspace::GetUserName()
  817. {
  818.     ASSERT_VALID(this);
  819.     ASSERT(m_pDAOWorkspace != NULL);
  820.  
  821.     COleVariant var;
  822.     DAO_CHECK(m_pDAOWorkspace->get_UserName(&V_BSTR(&var)));
  823.     var.vt = VT_BSTR;
  824.     return V_BSTRT(&var);
  825. }
  826.  
  827. void CDaoWorkspace::SetIsolateODBCTrans(BOOL bIsolateODBCTrans)
  828. {
  829.     ASSERT_VALID(this);
  830.     ASSERT(m_pDAOWorkspace != NULL);
  831.  
  832.     DAO_CHECK(m_pDAOWorkspace->put_IsolateODBCTrans(
  833.         (short)(bIsolateODBCTrans ? AFX_DAO_TRUE : AFX_DAO_FALSE)));
  834. }
  835.  
  836. BOOL CDaoWorkspace::GetIsolateODBCTrans()
  837. {
  838.     ASSERT_VALID(this);
  839.     ASSERT(m_pDAOWorkspace != NULL);
  840.  
  841.     short nIsolateODBCTrans;
  842.     DAO_CHECK(m_pDAOWorkspace->get_IsolateODBCTrans(&nIsolateODBCTrans));
  843.     return nIsolateODBCTrans == AFX_DAO_TRUE;
  844. }
  845.  
  846. void PASCAL CDaoWorkspace::CompactDatabase(LPCTSTR lpszSrcName,
  847.     LPCTSTR lpszDestName, LPCTSTR lpszLocale, int nOptions,
  848.     LPCTSTR lpszPassword)
  849. {
  850.     COleVariant varSrcName(lpszSrcName, VT_BSTRT);
  851.     COleVariant varDestName(lpszDestName, VT_BSTRT);
  852.  
  853.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  854.     if (pDaoState->m_pDAODBEngine == NULL)
  855.         InitializeEngine();
  856.  
  857.     DAO_CHECK(pDaoState->m_pDAODBEngine->CompactDatabase(
  858.         V_BSTR(&varSrcName), V_BSTR(&varDestName),
  859.         COleVariant(lpszLocale, VT_BSTRT), COleVariant((long)nOptions),
  860.         lpszPassword != NULL ? (VARIANT)COleVariant(lpszPassword, VT_BSTRT) :
  861.         _afxOptionalVariant));
  862. }
  863.  
  864. void PASCAL CDaoWorkspace::CompactDatabase(LPCTSTR lpszSrcName,
  865.     LPCTSTR lpszDestName, LPCTSTR lpszLocale, int nOptions)
  866. {
  867.     CompactDatabase(lpszSrcName, lpszDestName, lpszLocale, nOptions, NULL);
  868. }
  869.  
  870. void PASCAL CDaoWorkspace::RepairDatabase(LPCTSTR lpszName)
  871. {
  872.     COleVariant varName(lpszName, VT_BSTRT);
  873.  
  874.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  875.     if (pDaoState->m_pDAODBEngine == NULL)
  876.         InitializeEngine();
  877.  
  878.     DAO_CHECK(pDaoState->m_pDAODBEngine->RepairDatabase(
  879.         V_BSTR(&varName)));
  880. }
  881.  
  882. void PASCAL CDaoWorkspace::Idle(int nAction)
  883. {
  884.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  885.     if (pDaoState->m_pDAODBEngine == NULL)
  886.         InitializeEngine();
  887.  
  888.     DAO_CHECK(pDaoState->m_pDAODBEngine->Idle(
  889.         COleVariant((long)nAction)));
  890. }
  891.  
  892. short CDaoWorkspace::GetWorkspaceCount()
  893. {
  894.     ASSERT_VALID(this);
  895.  
  896.     short nFields;
  897.  
  898.     if (m_pDAOWorkspaces == NULL)
  899.         InitWorkspacesCollection();
  900.  
  901.     DAO_CHECK(m_pDAOWorkspaces->get_Count(&nFields));
  902.     return nFields;
  903. }
  904.  
  905. void CDaoWorkspace::GetWorkspaceInfo(int nIndex,
  906.     CDaoWorkspaceInfo& wsinfo, DWORD dwInfoOptions)
  907. {
  908.     ASSERT_VALID(this);
  909.  
  910.     if (m_pDAOWorkspaces == NULL)
  911.         InitWorkspacesCollection();
  912.  
  913.     // Get DAOWorkspace object and fill in workspace info struct
  914.     DAOWorkspace* pDAOWorkspace;
  915.     DAO_CHECK(m_pDAOWorkspaces->get_Item(
  916.         COleVariant((long)nIndex), &pDAOWorkspace));
  917.     FillWorkspaceInfo(pDAOWorkspace, wsinfo, dwInfoOptions);
  918.  
  919.     // Clean up
  920.     pDAOWorkspace->Release();
  921. }
  922.  
  923. void CDaoWorkspace::GetWorkspaceInfo(
  924.     LPCTSTR lpszName, CDaoWorkspaceInfo& wsinfo,
  925.     DWORD dwInfoOptions)
  926. {
  927.     ASSERT_VALID(this);
  928.  
  929.     if (m_pDAOWorkspaces == NULL)
  930.         InitWorkspacesCollection();
  931.  
  932.     // Get DAOWorkspace object and fill in workspace info struct
  933.     DAOWorkspace* pDAOWorkspace;
  934.     DAO_CHECK(m_pDAOWorkspaces->get_Item(
  935.         COleVariant(lpszName, VT_BSTRT), &pDAOWorkspace));
  936.     FillWorkspaceInfo(pDAOWorkspace, wsinfo, dwInfoOptions);
  937.  
  938.     // Clean up
  939.     pDAOWorkspace->Release();
  940. }
  941.  
  942. short CDaoWorkspace::GetDatabaseCount()
  943. {
  944.     ASSERT_VALID(this);
  945.  
  946.     if (m_pDAODatabases == NULL)
  947.         InitDatabasesCollection();
  948.  
  949.     short nFields;
  950.     DAO_CHECK(m_pDAODatabases->get_Count(&nFields));
  951.     return nFields;
  952. }
  953.  
  954. void CDaoWorkspace::GetDatabaseInfo(int nIndex, CDaoDatabaseInfo& dbinfo,
  955.     DWORD dwInfoOptions)
  956. {
  957.     ASSERT_VALID(this);
  958.  
  959.     if (m_pDAODatabases == NULL)
  960.         InitDatabasesCollection();
  961.  
  962.     // Get DAODatabase object and fill in database info struct
  963.     DAODatabase* pDAODatabase;
  964.     DAO_CHECK(m_pDAODatabases->get_Item(
  965.         COleVariant((long)nIndex), &pDAODatabase));
  966.     FillDatabaseInfo(pDAODatabase, dbinfo, dwInfoOptions);
  967.  
  968.     // Clean up
  969.     pDAODatabase->Release();
  970. }
  971.  
  972. void CDaoWorkspace::GetDatabaseInfo(LPCTSTR lpszName,
  973.     CDaoDatabaseInfo& dbinfo, DWORD dwInfoOptions)
  974. {
  975.     ASSERT_VALID(this);
  976.  
  977.     if (m_pDAODatabases == NULL)
  978.         InitDatabasesCollection();
  979.  
  980.     // Get DAODatabase object and fill in database info struct
  981.     DAODatabase* pDAODatabase;
  982.     DAO_CHECK(m_pDAODatabases->get_Item(
  983.         COleVariant(lpszName, VT_BSTRT), &pDAODatabase));
  984.     FillDatabaseInfo(pDAODatabase, dbinfo, dwInfoOptions);
  985.  
  986.     // Clean up
  987.     pDAODatabase->Release();
  988. }
  989.  
  990. void CDaoWorkspace::BeginTrans()
  991. {
  992.     ASSERT_VALID(this);
  993.     ASSERT(IsOpen());
  994.     ASSERT(m_pDAOWorkspace != NULL);
  995.  
  996.     DAO_CHECK(m_pDAOWorkspace->BeginTrans());
  997. }
  998.  
  999. // Determine whether to use DAO 3.6, 3.5, or 3.0
  1000. // Use DAO 3.0 if DLL build and not built with MFC 4.21 or later
  1001. // Use DAO 3.6 if MFC 6.01 or later
  1002. // otherwise, DAO 3.5
  1003.  
  1004. #ifndef _AFXDLL
  1005. #if _MFC_VER >= 0x0601
  1006. #define _AfxDetermineDaoVersion()   (36)
  1007. #else
  1008. #define _AfxDetermineDaoVersion()   (35)
  1009. #endif
  1010. #else // dynamically because of DLL
  1011. static inline BYTE _AfxDetermineDaoVersion()
  1012. {
  1013.     BYTE bReturn = 35;
  1014.  
  1015. #ifdef _AFXDLL
  1016.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  1017.     if (pModuleState->m_dwVersion < 0x421)
  1018.         bReturn = 30;
  1019.     else if (pModuleState->m_dwVersion >= 0x0601)
  1020.         bReturn = 36;
  1021. #endif // _AFXDLL
  1022.  
  1023.     return bReturn;
  1024. }
  1025. #endif
  1026.  
  1027. void CDaoWorkspace::CommitTrans()
  1028. {
  1029.     ASSERT_VALID(this);
  1030.     ASSERT(IsOpen());
  1031.     ASSERT(m_pDAOWorkspace != NULL);
  1032.  
  1033.    BYTE bUseDao = _AfxDetermineDaoVersion();
  1034.  
  1035.     if (bUseDao == 35 || bUseDao == 36)
  1036.     {
  1037.         // Call DAO 3.5 or 3.6 method with no option set.
  1038.         // CommitTrans option parameter not yet supported.
  1039.         DAO_CHECK(m_pDAOWorkspace->CommitTrans(0));
  1040.     }
  1041.     else
  1042.     {
  1043.         // Call DAO 3.0 method
  1044.         // The DAO 3.0 version of CommitTrans takes no params
  1045.         // so cast CommitTrans to method that takes no params.
  1046.         HRESULT (STDMETHODCALLTYPE DAOWorkspace::*pMethod)() = (HRESULT (STDMETHODCALLTYPE DAOWorkspace::*)())m_pDAOWorkspace->CommitTrans;
  1047.         DAO_CHECK((m_pDAOWorkspace->*pMethod)());
  1048.     }
  1049. }
  1050.  
  1051. void CDaoWorkspace::Rollback()
  1052. {
  1053.     ASSERT_VALID(this);
  1054.     ASSERT(IsOpen());
  1055.     ASSERT(m_pDAOWorkspace != NULL);
  1056.  
  1057.     DAO_CHECK(m_pDAOWorkspace->Rollback());
  1058. }
  1059.  
  1060. //Implementation
  1061. void AFX_CDECL CDaoWorkspace::InitializeEngine()
  1062. {
  1063.     AfxDaoInit();
  1064. }
  1065.  
  1066. void CDaoWorkspace::InitWorkspacesCollection()
  1067. {
  1068.     ASSERT_VALID(this);
  1069.  
  1070.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  1071.     if (pDaoState->m_pDAODBEngine == NULL)
  1072.         InitializeEngine();
  1073.  
  1074.     DAO_CHECK(pDaoState->m_pDAODBEngine->get_Workspaces(
  1075.         &m_pDAOWorkspaces));
  1076. }
  1077.  
  1078. void CDaoWorkspace::FillWorkspaceInfo(DAOWorkspace* pDAOWorkspace,
  1079.     CDaoWorkspaceInfo& wsinfo, DWORD dwOptions)
  1080. {
  1081.     ASSERT_VALID(this);
  1082.     ASSERT(pDAOWorkspace != NULL);
  1083.     ASSERT(dwOptions != 0);
  1084.  
  1085.     COleVariant var;
  1086.     short nBool;
  1087.  
  1088.     if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  1089.     {
  1090.         DAO_CHECK(pDAOWorkspace->get_Name(&V_BSTR(&var)));
  1091.         var.vt = VT_BSTR;
  1092.         wsinfo.m_strName = V_BSTRT(&var);
  1093.         var.Clear();
  1094.     }
  1095.  
  1096.     if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
  1097.     {
  1098.         DAO_CHECK(pDAOWorkspace->get_UserName(&V_BSTR(&var)));
  1099.         var.vt = VT_BSTR;
  1100.         wsinfo.m_strUserName = V_BSTRT(&var);
  1101.         var.Clear();
  1102.     }
  1103.  
  1104.     if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
  1105.     {
  1106.         DAO_CHECK(pDAOWorkspace->get_IsolateODBCTrans(&nBool));
  1107.         wsinfo.m_bIsolateODBCTrans = nBool == AFX_DAO_TRUE;
  1108.     }
  1109. }
  1110.  
  1111. void CDaoWorkspace::InitDatabasesCollection()
  1112. {
  1113.     ASSERT_VALID(this);
  1114.  
  1115.     DAO_CHECK(m_pDAOWorkspace->get_Databases(&m_pDAODatabases));
  1116. }
  1117.  
  1118. void CDaoWorkspace::FillDatabaseInfo(DAODatabase* pDAODatabase,
  1119.     CDaoDatabaseInfo& dbinfo, DWORD dwOptions)
  1120. {
  1121.     ASSERT_VALID(this);
  1122.     ASSERT(pDAODatabase != NULL);
  1123.     ASSERT(dwOptions != 0);
  1124.  
  1125.     COleVariant var;
  1126.     short nBool;
  1127.  
  1128.     if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  1129.     {
  1130.         DAO_CHECK(pDAODatabase->get_Name(&V_BSTR(&var)));
  1131.         var.vt = VT_BSTR;
  1132.         dbinfo.m_strName = V_BSTRT(&var);
  1133.         var.Clear();
  1134.  
  1135.         DAO_CHECK(pDAODatabase->get_Updatable(&nBool));
  1136.         dbinfo.m_bUpdatable = nBool == AFX_DAO_TRUE;
  1137.  
  1138.         DAO_CHECK(pDAODatabase->get_Transactions(&nBool));
  1139.         dbinfo.m_bTransactions = nBool == AFX_DAO_TRUE;
  1140.     }
  1141.  
  1142.     if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
  1143.     {
  1144.         DAO_CHECK(pDAODatabase->get_Version(
  1145.             &V_BSTR(&var)));
  1146.         var.vt = VT_BSTR;
  1147.         dbinfo.m_strVersion = V_BSTRT(&var);
  1148.         var.Clear();
  1149.  
  1150.         DAO_CHECK(pDAODatabase->get_CollatingOrder(
  1151.             &dbinfo.m_lCollatingOrder));
  1152.  
  1153.         DAO_CHECK(pDAODatabase->get_QueryTimeout(
  1154.             &dbinfo.m_nQueryTimeout));
  1155.     }
  1156.  
  1157.     if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
  1158.     {
  1159.         DAO_CHECK(pDAODatabase->get_Connect(
  1160.             &V_BSTR(&var)));
  1161.         var.vt = VT_BSTR;
  1162.         dbinfo.m_strConnect = V_BSTRT(&var);
  1163.         var.Clear();
  1164.     }
  1165. }
  1166.  
  1167. void CDaoWorkspace::ThrowDaoException(int nAfxDaoError)
  1168. {
  1169.     ASSERT_VALID(this);
  1170.  
  1171.     AfxThrowDaoException(nAfxDaoError);
  1172. }
  1173.  
  1174. #ifdef _DEBUG
  1175. void CDaoWorkspace::AssertValid() const
  1176. {
  1177.     CObject::AssertValid();
  1178. }
  1179.  
  1180. void CDaoWorkspace::Dump(CDumpContext& dc) const
  1181. {
  1182.     ASSERT_VALID(this);
  1183.  
  1184.     CObject::Dump(dc);
  1185.  
  1186.     dc << "m_bOpen = " << m_bOpen;
  1187.     dc << "\nm_bNew = " << m_bNew;
  1188.     dc << "\nm_nStatus = " << m_nStatus;
  1189.  
  1190.     dc << "\n";
  1191. }
  1192. #endif //_DEBUG
  1193.  
  1194. //////////////////////////////////////////////////////////////////////////
  1195. // CDaoDatabase
  1196. IMPLEMENT_DYNAMIC(CDaoDatabase, CObject)
  1197.  
  1198. CDaoDatabase::CDaoDatabase(CDaoWorkspace* pWorkspace)
  1199. {
  1200.     m_bOpen = FALSE;
  1201.  
  1202.     m_pDAODatabase = NULL;
  1203.  
  1204.     m_pDAOTableDefs = NULL;
  1205.     m_pDAORelations = NULL;
  1206.     m_pDAOQueryDefs = NULL;
  1207.     m_pDAORecordsets = NULL;
  1208.  
  1209.     m_pWorkspace = pWorkspace;
  1210.     m_nStatus = 0;
  1211. }
  1212.  
  1213. CDaoDatabase::~CDaoDatabase()
  1214. {
  1215.     if (IsOpen())
  1216.         Close();
  1217.  
  1218.     // Clean up workspace if necessary
  1219.     if (m_pWorkspace != NULL && (m_nStatus & AFX_DAO_IMPLICIT_WS))
  1220.     {
  1221.         m_pWorkspace->Close();
  1222.         delete m_pWorkspace;
  1223.         m_pWorkspace = NULL;
  1224.     }
  1225. }
  1226.  
  1227. void CDaoDatabase::Create(LPCTSTR lpszName, LPCTSTR lpszLocale,
  1228.     int nOptions)
  1229. {
  1230.     ASSERT_VALID(this);
  1231.     ASSERT(!IsOpen());
  1232.  
  1233.     // Allocate and maintain workspace if necessary
  1234.     InitWorkspace();
  1235.  
  1236.     COleVariant varName(lpszName, VT_BSTRT);
  1237.     COleVariant varLocale(lpszLocale, VT_BSTRT);
  1238.  
  1239.     DAO_CHECK(m_pWorkspace->m_pDAOWorkspace->CreateDatabase(V_BSTR(&varName),
  1240.         V_BSTR(&varLocale), COleVariant((long)nOptions),
  1241.         &m_pDAODatabase));
  1242.  
  1243.     m_bOpen = TRUE;
  1244.  
  1245.     // Add the database to map of Open CDaoDatabases
  1246.     m_pWorkspace->m_mapDatabases.SetAt(this, this);
  1247. }
  1248.  
  1249. void CDaoDatabase::Open(LPCTSTR lpszName, BOOL bExclusive,
  1250.     BOOL bReadOnly, LPCTSTR lpszConnect)
  1251. {
  1252.     ASSERT_VALID(this);
  1253.  
  1254.     // Re-Opening is invalid.
  1255.     if (IsOpen())
  1256.     {
  1257.         ASSERT(FALSE);
  1258.         return;
  1259.     }
  1260.  
  1261.     // Allocate, maintain and/or open workspace if necessary
  1262.     InitWorkspace();
  1263.  
  1264.     COleVariant var(lpszName, VT_BSTRT);
  1265.  
  1266.     DAO_CHECK(m_pWorkspace->m_pDAOWorkspace->OpenDatabase(
  1267.         V_BSTR(&var),
  1268.         COleVariant((long)bExclusive, VT_BOOL),
  1269.         COleVariant((long)bReadOnly, VT_BOOL),
  1270.         COleVariant(lpszConnect, VT_BSTRT),
  1271.         &m_pDAODatabase));
  1272.  
  1273.     m_bOpen = TRUE;
  1274.  
  1275.     // Add the database to map of Open CDaoDatabases
  1276.     m_pWorkspace->m_mapDatabases.SetAt(this, this);
  1277. }
  1278.  
  1279. // Disconnect connection
  1280. void CDaoDatabase::Close()
  1281. {
  1282.     ASSERT_VALID(this);
  1283.  
  1284.     if (m_pDAORecordsets != NULL)
  1285.     {
  1286.         m_pDAORecordsets->Release();
  1287.         m_pDAORecordsets = NULL;
  1288.     }
  1289.  
  1290.     if (m_pDAOQueryDefs != NULL)
  1291.     {
  1292.         m_pDAOQueryDefs->Release();
  1293.         m_pDAOQueryDefs = NULL;
  1294.     }
  1295.  
  1296.     if (m_pDAORelations != NULL)
  1297.     {
  1298.         m_pDAORelations->Release();
  1299.         m_pDAORelations = NULL;
  1300.     }
  1301.  
  1302.     if (m_pDAOTableDefs != NULL)
  1303.     {
  1304.         m_pDAOTableDefs->Release();
  1305.         m_pDAOTableDefs = NULL;
  1306.     }
  1307.  
  1308.     // Close any Open CDaoRecordsets
  1309.     void* pvKey;
  1310.     void* pvObject;
  1311.     POSITION pos = m_mapRecordsets.GetStartPosition();
  1312.     while (pos != NULL)
  1313.     {
  1314.         m_mapRecordsets.GetNextAssoc(pos, pvKey, pvObject);
  1315.         ((CDaoRecordset*)pvObject)->Close();
  1316.     }
  1317.     m_mapRecordsets.RemoveAll();
  1318.  
  1319.     // Close any Open CDaoQueryDefs
  1320.     pos = m_mapQueryDefs.GetStartPosition();
  1321.     while (pos != NULL)
  1322.     {
  1323.         m_mapQueryDefs.GetNextAssoc(pos, pvKey, pvObject);
  1324.         ((CDaoQueryDef*)pvObject)->Close();
  1325.     }
  1326.     m_mapQueryDefs.RemoveAll();
  1327.  
  1328.     // Close any Open CDaoTableDefs
  1329.     pos = m_mapTableDefs.GetStartPosition();
  1330.     while (pos != NULL)
  1331.     {
  1332.         m_mapTableDefs.GetNextAssoc(pos, pvKey, pvObject);
  1333.         ((CDaoTableDef*)pvObject)->Close();
  1334.     }
  1335.     m_mapTableDefs.RemoveAll();
  1336.  
  1337.     if (m_pDAODatabase != NULL)
  1338.     {
  1339.         // If implicit database, don't close.
  1340.         // It will be automatically closed when ref count 0.
  1341.         if (!(m_nStatus & AFX_DAO_IMPLICIT_DB))
  1342.             DAO_TRACE(m_pDAODatabase->Close());
  1343.  
  1344.         m_pDAODatabase->Release();
  1345.         m_pDAODatabase = NULL;
  1346.     }
  1347.  
  1348.     m_bOpen = FALSE;
  1349.  
  1350.     // Remove the CDaoDatabase from the CDaoWorkspace's map
  1351.     m_pWorkspace->m_mapDatabases.RemoveKey(this);
  1352. }
  1353.  
  1354. BOOL CDaoDatabase::CanUpdate()
  1355. {
  1356.     ASSERT_VALID(this);
  1357.     ASSERT(IsOpen());
  1358.     ASSERT(m_pDAODatabase != NULL);
  1359.  
  1360.     short nUpdatable;
  1361.     DAO_CHECK(m_pDAODatabase->get_Updatable(&nUpdatable));
  1362.     return nUpdatable == AFX_DAO_TRUE;
  1363. }
  1364.  
  1365. BOOL CDaoDatabase::CanTransact()
  1366. {
  1367.     ASSERT_VALID(this);
  1368.     ASSERT(IsOpen());
  1369.     ASSERT(m_pDAODatabase != NULL);
  1370.  
  1371.     short nTransactable;
  1372.     DAO_CHECK(m_pDAODatabase->get_Transactions(&nTransactable));
  1373.     return nTransactable == AFX_DAO_TRUE;
  1374. }
  1375.  
  1376. CString CDaoDatabase::GetName()
  1377. {
  1378.     ASSERT_VALID(this);
  1379.     ASSERT(IsOpen());
  1380.     ASSERT(m_pDAODatabase != NULL);
  1381.  
  1382.     COleVariant var;
  1383.     DAO_CHECK(m_pDAODatabase->get_Name(&V_BSTR(&var)));
  1384.     var.vt = VT_BSTR;
  1385.     return V_BSTRT(&var);
  1386. }
  1387.  
  1388. CString CDaoDatabase::GetConnect()
  1389. {
  1390.     ASSERT_VALID(this);
  1391.     ASSERT(IsOpen());
  1392.     ASSERT(m_pDAODatabase != NULL);
  1393.  
  1394.     COleVariant var;
  1395.     DAO_CHECK(m_pDAODatabase->get_Connect(&V_BSTR(&var)));
  1396.     var.vt = VT_BSTR;
  1397.     return V_BSTRT(&var);
  1398. }
  1399.  
  1400. CString CDaoDatabase::GetVersion()
  1401. {
  1402.     ASSERT_VALID(this);
  1403.     ASSERT(IsOpen());
  1404.     ASSERT(m_pDAODatabase != NULL);
  1405.  
  1406.     COleVariant var;
  1407.     DAO_CHECK(m_pDAODatabase->get_Version(&V_BSTR(&var)));
  1408.     var.vt = VT_BSTR;
  1409.     return V_BSTRT(&var);
  1410. }
  1411.  
  1412. short CDaoDatabase::GetQueryTimeout()
  1413. {
  1414.     ASSERT_VALID(this);
  1415.     ASSERT(IsOpen());
  1416.     ASSERT(m_pDAODatabase != NULL);
  1417.  
  1418.     short nQueryTimeout;
  1419.     DAO_CHECK(m_pDAODatabase->get_QueryTimeout(&nQueryTimeout));
  1420.     return nQueryTimeout;
  1421. }
  1422.  
  1423. void CDaoDatabase::SetQueryTimeout(short nSeconds)
  1424. {
  1425.     ASSERT_VALID(this);
  1426.     ASSERT(IsOpen());
  1427.     ASSERT(m_pDAODatabase != NULL);
  1428.  
  1429.     DAO_CHECK(m_pDAODatabase->put_QueryTimeout(nSeconds));
  1430. }
  1431.  
  1432. long CDaoDatabase::GetRecordsAffected()
  1433. {
  1434.     ASSERT_VALID(this);
  1435.     ASSERT(IsOpen());
  1436.     ASSERT(m_pDAODatabase != NULL);
  1437.  
  1438.     long lRecordsAffected;
  1439.     DAO_CHECK(m_pDAODatabase->get_RecordsAffected(&lRecordsAffected));
  1440.     return lRecordsAffected;
  1441. }
  1442.  
  1443. void CDaoDatabase::DeleteTableDef(LPCTSTR lpszName)
  1444. {
  1445.     ASSERT_VALID(this);
  1446.     ASSERT(IsOpen());
  1447.  
  1448.     if (m_pDAOTableDefs == NULL)
  1449.         InitTableDefsCollection();
  1450.  
  1451.     COleVariant var(lpszName, VT_BSTRT);
  1452.     DAO_CHECK(m_pDAOTableDefs->Delete(V_BSTR(&var)));
  1453. }
  1454.  
  1455. void CDaoDatabase::DeleteQueryDef(LPCTSTR lpszName)
  1456. {
  1457.     ASSERT_VALID(this);
  1458.     ASSERT(IsOpen());
  1459.  
  1460.     if (m_pDAOQueryDefs == NULL)
  1461.         InitQueryDefsCollection();
  1462.  
  1463.     COleVariant var(lpszName, VT_BSTRT);
  1464.     DAO_CHECK(m_pDAOQueryDefs->Delete(V_BSTR(&var)));
  1465. }
  1466.  
  1467. void CDaoDatabase::CreateRelation(LPCTSTR lpszName, LPCTSTR lpszTable,
  1468.     LPCTSTR lpszForeignTable, long lAttributes, LPCTSTR lpszField,
  1469.     LPCTSTR lpszForeignField)
  1470. {
  1471.     ASSERT_VALID(this);
  1472.  
  1473.     CDaoRelationInfo relinfo;
  1474.     CDaoRelationFieldInfo fieldinfo;
  1475.  
  1476.     relinfo.m_strName = lpszName;
  1477.     relinfo.m_strTable = lpszTable;
  1478.     relinfo.m_strForeignTable = lpszForeignTable;
  1479.     relinfo.m_lAttributes = lAttributes;
  1480.     relinfo.m_nFields = 1;
  1481.  
  1482.     relinfo.m_pFieldInfos = &fieldinfo;
  1483.     relinfo.m_pFieldInfos->m_strName = lpszField;
  1484.     relinfo.m_pFieldInfos->m_strForeignName = lpszForeignField;
  1485.  
  1486.     CreateRelation(relinfo);
  1487. }
  1488.  
  1489. void CDaoDatabase::CreateRelation(CDaoRelationInfo& relinfo)
  1490. {
  1491.     ASSERT_VALID(this);
  1492.     ASSERT(IsOpen());
  1493.     ASSERT(relinfo.m_nFields > 0);
  1494.  
  1495.     // Initialize relations collection so that relation can be appended later
  1496.     if (m_pDAORelations == NULL)
  1497.         InitRelationsCollection();
  1498.  
  1499.     DAORelation* pDAORelation = NULL;
  1500.     DAOFields* pDAOFields = NULL;
  1501.     DAOField* pDAOField = NULL;
  1502.  
  1503.     // Create the relation
  1504.     DAO_CHECK(m_pDAODatabase->CreateRelation(
  1505.         COleVariant(relinfo.m_strName, VT_BSTRT),
  1506.         COleVariant(relinfo.m_strTable, VT_BSTRT),
  1507.         COleVariant(relinfo.m_strForeignTable, VT_BSTRT),
  1508.         COleVariant(relinfo.m_lAttributes), &pDAORelation));
  1509.  
  1510.     TRY
  1511.     {
  1512.         // Get the fields collection for later append of created field
  1513.         DAO_CHECK(pDAORelation->get_Fields(&pDAOFields));
  1514.  
  1515.         // Create field(s) and set the name and foreign name
  1516.         for (int nIndex = 0; nIndex < relinfo.m_nFields; nIndex++)
  1517.         {
  1518.             DAO_CHECK(pDAORelation->CreateField(
  1519.                 COleVariant(relinfo.m_pFieldInfos[nIndex].m_strName, VT_BSTRT),
  1520.                 _afxOptionalVariant, _afxOptionalVariant, &pDAOField));
  1521.  
  1522.             COleVariant var(relinfo.m_pFieldInfos[nIndex].m_strForeignName, VT_BSTRT);
  1523.             DAO_CHECK(pDAOField->put_ForeignName(V_BSTR(&var)));
  1524.  
  1525.             // Append the field to relation fields collection and release
  1526.             DAO_CHECK(pDAOFields->Append(pDAOField));
  1527.             pDAOField->Release();
  1528.         }
  1529.  
  1530.         DAO_CHECK(m_pDAORelations->Append(pDAORelation));
  1531.     }
  1532.     CATCH_ALL(e)
  1533.     {
  1534.         // Clean up before throw
  1535.         if (pDAOField != NULL)
  1536.             pDAOField->Release();
  1537.  
  1538.         if (pDAOFields != NULL)
  1539.             pDAOFields->Release();
  1540.  
  1541.         pDAORelation->Release();
  1542.         THROW_LAST();
  1543.     }
  1544.     END_CATCH_ALL
  1545.  
  1546.     // Clean up
  1547.     if (pDAOField != NULL)
  1548.         pDAOField->Release();
  1549.  
  1550.     pDAOFields->Release();
  1551.     pDAORelation->Release();
  1552. }
  1553.  
  1554. void CDaoDatabase::DeleteRelation(LPCTSTR lpszName)
  1555. {
  1556.     ASSERT_VALID(this);
  1557.     ASSERT(IsOpen());
  1558.  
  1559.     if (m_pDAORelations == NULL)
  1560.         InitRelationsCollection();
  1561.  
  1562.     COleVariant var(lpszName, VT_BSTRT);
  1563.     DAO_CHECK(m_pDAORelations->Delete(V_BSTR(&var)));
  1564. }
  1565.  
  1566. void CDaoDatabase::Execute(LPCTSTR lpszSQL, int nOptions)
  1567. {
  1568.     ASSERT_VALID(this);
  1569.     ASSERT(m_pDAODatabase != NULL);
  1570.  
  1571.     COleVariant var(lpszSQL, VT_BSTRT);
  1572.     DAO_CHECK(m_pDAODatabase->Execute(
  1573.         V_BSTR(&var), COleVariant((long)nOptions)));
  1574. }
  1575.  
  1576. short CDaoDatabase::GetTableDefCount()
  1577. {
  1578.     ASSERT_VALID(this);
  1579.  
  1580.     short nTables;
  1581.  
  1582.     if (m_pDAOTableDefs == NULL)
  1583.         InitTableDefsCollection();
  1584.  
  1585.     DAO_CHECK(m_pDAOTableDefs->get_Count(&nTables));
  1586.     return nTables;
  1587. }
  1588.  
  1589. void CDaoDatabase::GetTableDefInfo(int nIndex, CDaoTableDefInfo& tabledefinfo,
  1590.     DWORD dwInfoOptions)
  1591. {
  1592.     ASSERT_VALID(this);
  1593.  
  1594.     if (m_pDAOTableDefs == NULL)
  1595.         InitTableDefsCollection();
  1596.  
  1597.     // Get DAOTableDef object and fill in table info struct
  1598.     DAOTableDef* pDAOTableDef;
  1599.     DAO_CHECK(m_pDAOTableDefs->get_Item(
  1600.         COleVariant((long)nIndex), &pDAOTableDef));
  1601.     FillTableDefInfo(pDAOTableDef, tabledefinfo, dwInfoOptions);
  1602.  
  1603.     // Clean up
  1604.     pDAOTableDef->Release();
  1605. }
  1606.  
  1607. void CDaoDatabase::GetTableDefInfo(LPCTSTR lpszName,
  1608.     CDaoTableDefInfo&  tabledefinfo, DWORD dwInfoOptions)
  1609. {
  1610.     ASSERT_VALID(this);
  1611.  
  1612.     if (m_pDAOTableDefs == NULL)
  1613.         InitTableDefsCollection();
  1614.  
  1615.     // Get DAOTableDef object and fill in table info struct
  1616.     DAOTableDef* pDAOTableDef;
  1617.     DAO_CHECK(m_pDAOTableDefs->get_Item(
  1618.         COleVariant(lpszName, VT_BSTRT), &pDAOTableDef));
  1619.     FillTableDefInfo(pDAOTableDef, tabledefinfo, dwInfoOptions);
  1620.  
  1621.     // Clean up
  1622.     pDAOTableDef->Release();
  1623. }
  1624.  
  1625. short CDaoDatabase::GetRelationCount()
  1626. {
  1627.     ASSERT_VALID(this);
  1628.  
  1629.     short nRelations;
  1630.  
  1631.     if (m_pDAORelations == NULL)
  1632.         InitRelationsCollection();
  1633.  
  1634.     DAO_CHECK(m_pDAORelations->get_Count(&nRelations));
  1635.     return nRelations;
  1636. }
  1637.  
  1638. void CDaoDatabase::GetRelationInfo(int nIndex, CDaoRelationInfo& relinfo,
  1639.     DWORD dwInfoOptions)
  1640. {
  1641.     ASSERT_VALID(this);
  1642.  
  1643.     if (m_pDAORelations == NULL)
  1644.         InitRelationsCollection();
  1645.  
  1646.     // Get DAORelation object and fill in relation info struct
  1647.     DAORelation* pDAORelation;
  1648.     DAO_CHECK(m_pDAORelations->get_Item(
  1649.         COleVariant((long)nIndex), &pDAORelation));
  1650.     FillRelationInfo(pDAORelation, relinfo, dwInfoOptions);
  1651.  
  1652.     // Clean up
  1653.     pDAORelation->Release();
  1654. }
  1655.  
  1656. void CDaoDatabase::GetRelationInfo(LPCTSTR lpszName,
  1657.     CDaoRelationInfo& relinfo, DWORD dwInfoOptions)
  1658. {
  1659.     ASSERT_VALID(this);
  1660.  
  1661.     if (m_pDAORelations == NULL)
  1662.         InitRelationsCollection();
  1663.  
  1664.     // Get DAORelation object and fill in relation info struct
  1665.     DAORelation* pDAORelation;
  1666.     DAO_CHECK(m_pDAORelations->get_Item(
  1667.         COleVariant(lpszName, VT_BSTRT), &pDAORelation));
  1668.     FillRelationInfo(pDAORelation, relinfo, dwInfoOptions);
  1669.  
  1670.     // Clean up
  1671.     pDAORelation->Release();
  1672. }
  1673.  
  1674. short CDaoDatabase::GetQueryDefCount()
  1675. {
  1676.     ASSERT_VALID(this);
  1677.  
  1678.     short nQueryDefs;
  1679.  
  1680.     if (m_pDAOQueryDefs == NULL)
  1681.         InitQueryDefsCollection();
  1682.  
  1683.     DAO_CHECK(m_pDAOQueryDefs->get_Count(&nQueryDefs));
  1684.     return nQueryDefs;
  1685. }
  1686.  
  1687. void CDaoDatabase::GetQueryDefInfo(int nIndex, CDaoQueryDefInfo& querydefinfo,
  1688.     DWORD dwInfoOptions)
  1689. {
  1690.     ASSERT_VALID(this);
  1691.  
  1692.     if (m_pDAOQueryDefs == NULL)
  1693.         InitQueryDefsCollection();
  1694.  
  1695.     // Get DAOQueryDef object and fill in query info struct
  1696.     DAOQueryDef* pDAOQueryDef;
  1697.     DAO_CHECK(m_pDAOQueryDefs->get_Item(
  1698.         COleVariant((long)nIndex), &pDAOQueryDef));
  1699.     FillQueryDefInfo(pDAOQueryDef, querydefinfo, dwInfoOptions);
  1700.  
  1701.     // Clean up
  1702.     pDAOQueryDef->Release();
  1703. }
  1704.  
  1705. void CDaoDatabase::GetQueryDefInfo(LPCTSTR lpszName,
  1706.     CDaoQueryDefInfo& querydefinfo, DWORD dwInfoOptions)
  1707. {
  1708.     ASSERT_VALID(this);
  1709.  
  1710.     if (m_pDAOQueryDefs == NULL)
  1711.         InitQueryDefsCollection();
  1712.  
  1713.     // Get DAOQueryDef object and fill in query info struct
  1714.     DAOQueryDef* pDAOQueryDef;
  1715.     DAO_CHECK(m_pDAOQueryDefs->get_Item(
  1716.         COleVariant(lpszName, VT_BSTRT), &pDAOQueryDef));
  1717.     FillQueryDefInfo(pDAOQueryDef, querydefinfo, dwInfoOptions);
  1718.  
  1719.     // Clean up
  1720.     pDAOQueryDef->Release();
  1721. }
  1722.  
  1723. // Implementation
  1724. void CDaoDatabase::InitWorkspace()
  1725. {
  1726.     ASSERT_VALID(this);
  1727.  
  1728.     if (m_pWorkspace == NULL)
  1729.     {
  1730.         // Allocate workspace and mark as implicit
  1731.         m_pWorkspace = new CDaoWorkspace;
  1732.         m_pWorkspace->m_nStatus |= AFX_DAO_IMPLICIT_WS;
  1733.         m_nStatus |= AFX_DAO_IMPLICIT_WS;
  1734.     }
  1735.  
  1736.     // Open workspace if not open and not new (unappended)
  1737.     if (!m_pWorkspace->IsOpen() && !m_pWorkspace->IsNew())
  1738.     {
  1739.         // Open the default workspace
  1740.         m_pWorkspace->Open();
  1741.     }
  1742. }
  1743.  
  1744. void CDaoDatabase::InitTableDefsCollection()
  1745. {
  1746.     ASSERT_VALID(this);
  1747.  
  1748.     DAO_CHECK(m_pDAODatabase->get_TableDefs(&m_pDAOTableDefs));
  1749. }
  1750.  
  1751. void CDaoDatabase::FillTableDefInfo(DAOTableDef* pDAOTableDef,
  1752.     CDaoTableDefInfo& tabledefinfo, DWORD dwOptions)
  1753. {
  1754.     ASSERT_VALID(this);
  1755.     ASSERT(pDAOTableDef != NULL);
  1756.     ASSERT(dwOptions != 0);
  1757.  
  1758.     COleVariant var;
  1759.     short nBool;
  1760.  
  1761.     if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  1762.     {
  1763.         DAO_CHECK(pDAOTableDef->get_Name(&V_BSTR(&var)));
  1764.         var.vt = VT_BSTR;
  1765.         tabledefinfo.m_strName = V_BSTRT(&var);
  1766.         var.Clear();
  1767.  
  1768.         DAO_CHECK(pDAOTableDef->get_Updatable(&nBool));
  1769.         tabledefinfo.m_bUpdatable = nBool == AFX_DAO_TRUE;
  1770.  
  1771.         DAO_CHECK(pDAOTableDef->get_Attributes(
  1772.             &tabledefinfo.m_lAttributes));
  1773.     }
  1774.  
  1775.     if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
  1776.     {
  1777.         DAO_CHECK(pDAOTableDef->get_DateCreated(&var));
  1778.         tabledefinfo.m_dateCreated = var;
  1779.  
  1780.         DAO_CHECK(pDAOTableDef->get_LastUpdated(&var));
  1781.         tabledefinfo.m_dateLastUpdated = var;
  1782.  
  1783.         DAO_CHECK(pDAOTableDef->get_SourceTableName(
  1784.             &V_BSTR(&var)));
  1785.         var.vt = VT_BSTR;
  1786.         tabledefinfo.m_strSrcTableName = V_BSTRT(&var);
  1787.         var.Clear();
  1788.  
  1789.         DAO_CHECK(pDAOTableDef->get_Connect(
  1790.             &V_BSTR(&var)));
  1791.         var.vt = VT_BSTR;
  1792.         tabledefinfo.m_strConnect = V_BSTRT(&var);
  1793.         var.Clear();
  1794.  
  1795.         DAO_CHECK(pDAOTableDef->get_ValidationRule(
  1796.             &V_BSTR(&var)));
  1797.         var.vt = VT_BSTR;
  1798.         tabledefinfo.m_strValidationRule = V_BSTRT(&var);
  1799.         var.Clear();
  1800.  
  1801.         DAO_CHECK(pDAOTableDef->get_ValidationText(
  1802.             &V_BSTR(&var)));
  1803.         var.vt = VT_BSTR;
  1804.         tabledefinfo.m_strValidationText = V_BSTRT(&var);
  1805.         var.Clear();
  1806.     }
  1807.  
  1808.     // This may be expensive, so only get it if absolutely necessary
  1809.     if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
  1810.     {
  1811.         DAO_CHECK(pDAOTableDef->get_RecordCount(
  1812.             &tabledefinfo.m_lRecordCount));
  1813.     }
  1814. }
  1815.  
  1816. void CDaoDatabase::InitRelationsCollection()
  1817. {
  1818.     ASSERT_VALID(this);
  1819.  
  1820.     DAO_CHECK(m_pDAODatabase->get_Relations(&m_pDAORelations));
  1821. }
  1822.  
  1823. void CDaoDatabase::FillRelationInfo(DAORelation* pDAORelation,
  1824.     CDaoRelationInfo& relinfo, DWORD dwOptions)
  1825. {
  1826.     ASSERT_VALID(this);
  1827.     ASSERT(pDAORelation != NULL);
  1828.     ASSERT(dwOptions != 0);
  1829.  
  1830.     COleVariant var;
  1831.  
  1832.     if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  1833.     {
  1834.         // All the relation info is primary
  1835.         DAO_CHECK(pDAORelation->get_Name(&V_BSTR(&var)));
  1836.         var.vt = VT_BSTR;
  1837.         relinfo.m_strName = V_BSTRT(&var);
  1838.         var.Clear();
  1839.  
  1840.         DAO_CHECK(pDAORelation->get_Table(&V_BSTR(&var)));
  1841.         var.vt = VT_BSTR;
  1842.         relinfo.m_strTable = V_BSTRT(&var);
  1843.         var.Clear();
  1844.  
  1845.         DAO_CHECK(pDAORelation->get_ForeignTable(
  1846.             &V_BSTR(&var)));
  1847.         var.vt = VT_BSTR;
  1848.         relinfo.m_strForeignTable = V_BSTRT(&var);
  1849.         var.Clear();
  1850.     }
  1851.  
  1852.     if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
  1853.     {
  1854.         DAOFields* pDAOFields = NULL;
  1855.         DAOField* pDAOField = NULL;
  1856.  
  1857.         DAO_CHECK(pDAORelation->get_Attributes(
  1858.             &relinfo.m_lAttributes));
  1859.  
  1860.         // Get the fields collection
  1861.         DAO_CHECK(pDAORelation->get_Fields(&pDAOFields));
  1862.  
  1863.         TRY
  1864.         {
  1865.             // Get the number of fields in the relation
  1866.             short nCount;
  1867.             DAO_CHECK(pDAOFields->get_Count(&nCount));
  1868.  
  1869.             // Allocate or reallocate memory for array if necessary
  1870.             if (nCount != relinfo.m_nFields)
  1871.             {
  1872.                 if (relinfo.m_nFields != 0)
  1873.                 {
  1874.                     // Check that allocation is correct.
  1875.                     ASSERT(relinfo.m_nFields == 0 ||
  1876.                         relinfo.m_bCleanupFieldInfo);
  1877.  
  1878.                     delete[] relinfo.m_pFieldInfos;
  1879.                     relinfo.m_pFieldInfos = NULL;
  1880.                 }
  1881.  
  1882.                 // Now allocate required memory
  1883.                 relinfo.m_pFieldInfos = new CDaoRelationFieldInfo[nCount];
  1884.                 relinfo.m_bCleanupFieldInfo = TRUE;
  1885.                 relinfo.m_nFields = nCount;
  1886.             }
  1887.  
  1888.             // Now get field info for each field
  1889.             for (int nIndex = 0; nIndex < relinfo.m_nFields; nIndex++)
  1890.             {
  1891.                 // Get the field item
  1892.                 DAO_CHECK(pDAOFields->get_Item(
  1893.                     COleVariant((long)nIndex), &pDAOField));
  1894.  
  1895.                 // Get the field name
  1896.                 DAO_CHECK(pDAOField->get_Name(&V_BSTR(&var)));
  1897.                 var.vt = VT_BSTR;
  1898.                 relinfo.m_pFieldInfos[nIndex].m_strName =
  1899.                     V_BSTRT(&var);
  1900.                 var.Clear();
  1901.  
  1902.                 // Get the foreign field name
  1903.                 DAO_CHECK(pDAOField->get_ForeignName(&V_BSTR(&var)));
  1904.                 var.vt = VT_BSTR;
  1905.                 relinfo.m_pFieldInfos[nIndex].m_strForeignName =
  1906.                     V_BSTRT(&var);
  1907.                 var.Clear();
  1908.  
  1909.                 // Release and reset the field object
  1910.                 pDAOField->Release();
  1911.                 pDAOField = NULL;
  1912.             }
  1913.         }
  1914.         CATCH_ALL(e)
  1915.         {
  1916.             if (pDAOField != NULL)
  1917.                 pDAOField->Release();
  1918.  
  1919.             pDAOFields->Release();
  1920.             THROW_LAST();
  1921.         }
  1922.         END_CATCH_ALL
  1923.  
  1924.         // Release the objects
  1925.         pDAOFields->Release();
  1926.     }
  1927. }
  1928.  
  1929. void CDaoDatabase::InitQueryDefsCollection()
  1930. {
  1931.     ASSERT_VALID(this);
  1932.  
  1933.     DAO_CHECK(m_pDAODatabase->get_QueryDefs(&m_pDAOQueryDefs));
  1934. }
  1935.  
  1936. void CDaoDatabase::FillQueryDefInfo(DAOQueryDef* pDAOQueryDef,
  1937.     CDaoQueryDefInfo& querydefinfo, DWORD dwOptions)
  1938. {
  1939.     ASSERT_VALID(this);
  1940.     ASSERT(pDAOQueryDef != NULL);
  1941.     ASSERT(dwOptions != 0);
  1942.  
  1943.     COleVariant var;
  1944.     short nBool;
  1945.  
  1946.     if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  1947.     {
  1948.         DAO_CHECK(pDAOQueryDef->get_Name(&V_BSTR(&var)));
  1949.         var.vt = VT_BSTR;
  1950.         querydefinfo.m_strName = V_BSTRT(&var);
  1951.         var.Clear();
  1952.  
  1953.         DAO_CHECK(pDAOQueryDef->get_Type(&querydefinfo.m_nType));
  1954.     }
  1955.  
  1956.     if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
  1957.     {
  1958.         DAO_CHECK(pDAOQueryDef->get_Updatable(&nBool));
  1959.         querydefinfo.m_bUpdatable = nBool == AFX_DAO_TRUE;
  1960.  
  1961.         DAO_CHECK(pDAOQueryDef->get_DateCreated(&var));
  1962.         querydefinfo.m_dateCreated = var;
  1963.  
  1964.         DAO_CHECK(pDAOQueryDef->get_LastUpdated(&var));
  1965.         querydefinfo.m_dateLastUpdated = var;
  1966.  
  1967.         DAO_CHECK(pDAOQueryDef->get_ReturnsRecords(&nBool));
  1968.         querydefinfo.m_bReturnsRecords = nBool == AFX_DAO_TRUE;
  1969.     }
  1970.  
  1971.     if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
  1972.     {
  1973.         DAO_CHECK(pDAOQueryDef->get_SQL(&V_BSTR(&var)));
  1974.         var.vt = VT_BSTR;
  1975.         querydefinfo.m_strSQL = V_BSTRT(&var);
  1976.         var.Clear();
  1977.  
  1978.         DAO_CHECK(pDAOQueryDef->get_Connect(&V_BSTR(
  1979.             (LPVARIANT)var)));
  1980.         var.vt = VT_BSTR;
  1981.         querydefinfo.m_strConnect = V_BSTRT(&var);
  1982.         var.Clear();
  1983.  
  1984.         // DAO will display ODBC connect dialog
  1985.         // if data source no longer exists. This must
  1986.         // be avoided during bulk info retrieval.
  1987.         // Call CDaoQueryDef::GetODBCTimeout directly.
  1988.         //  DAO_CHECK(pDAOQueryDef->get_ODBCTimeout(
  1989.         //      &querydefinfo.m_nODBCTimeout));
  1990.  
  1991.         // Set the m_nODBCTimeout variable to invalid value.
  1992.         querydefinfo.m_nODBCTimeout = -1;
  1993.     }
  1994. }
  1995.  
  1996. void CDaoDatabase::ThrowDaoException(int nAfxDaoError)
  1997. {
  1998.     ASSERT_VALID(this);
  1999.  
  2000.     AfxThrowDaoException(nAfxDaoError);
  2001. }
  2002.  
  2003. #ifdef _DEBUG
  2004. void CDaoDatabase::AssertValid() const
  2005. {
  2006.     CObject::AssertValid();
  2007. }
  2008.  
  2009. void CDaoDatabase::Dump(CDumpContext& dc) const
  2010. {
  2011.     ASSERT_VALID(this);
  2012.  
  2013.     CObject::Dump(dc);
  2014.  
  2015.     dc << "m_bOpen = " << m_bOpen;
  2016.     dc << "\nm_nStatus = " << m_nStatus;
  2017.  
  2018.     dc << "\n";
  2019. }
  2020. #endif //_DEBUG
  2021.  
  2022. //////////////////////////////////////////////////////////////////////////
  2023. // CDaoTableDef
  2024. IMPLEMENT_DYNAMIC(CDaoTableDef, CObject)
  2025.  
  2026. CDaoTableDef::CDaoTableDef(CDaoDatabase* pDatabase)
  2027. {
  2028.     m_bOpen = FALSE;
  2029.     m_bNew = FALSE;
  2030.  
  2031.     m_pDatabase = pDatabase;
  2032.     m_pDAOTableDef = NULL;
  2033.     m_pDAOFields = NULL;
  2034.     m_pDAOIndexes = NULL;
  2035. }
  2036.  
  2037. CDaoTableDef::~CDaoTableDef()
  2038. {
  2039.     if (IsOpen())
  2040.         Close();
  2041.     else if (m_bNew)
  2042.     {
  2043.         // Remove the tabledef from the CDaoDatabase's map
  2044.         m_pDatabase->m_mapTableDefs.RemoveKey(this);
  2045.     }
  2046. }
  2047.  
  2048. void CDaoTableDef::Create(LPCTSTR lpszName, long lAttributes,
  2049.     LPCTSTR lpszSrcTable, LPCTSTR lpszConnect)
  2050. {
  2051.     ASSERT_VALID(this);
  2052.     ASSERT(!IsOpen());
  2053.  
  2054.     DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateTableDef(
  2055.         COleVariant(lpszName, VT_BSTRT), COleVariant(lAttributes),
  2056.         COleVariant(lpszSrcTable, VT_BSTRT),
  2057.         COleVariant(lpszConnect, VT_BSTRT), &m_pDAOTableDef));
  2058.  
  2059.     m_bNew = TRUE;
  2060.  
  2061.     // Add the tabledef to map of Open/New CDaoTableDefs
  2062.     m_pDatabase->m_mapTableDefs.SetAt(this, this);
  2063. }
  2064.  
  2065. void CDaoTableDef::Append()
  2066. {
  2067.     ASSERT_VALID(this);
  2068.     ASSERT(m_bNew);
  2069.     ASSERT(m_pDAOTableDef != NULL);
  2070.  
  2071.     DAOTableDefs* pDAOTableDefs;
  2072.     DAO_CHECK(m_pDatabase->m_pDAODatabase->get_TableDefs(
  2073.         &pDAOTableDefs));
  2074.  
  2075.     TRY
  2076.     {
  2077.         DAO_CHECK(pDAOTableDefs->Append(m_pDAOTableDef));
  2078.     }
  2079.     CATCH_ALL(e)
  2080.     {
  2081.         pDAOTableDefs->Release();
  2082.         THROW_LAST();
  2083.     }
  2084.     END_CATCH_ALL
  2085.  
  2086.     pDAOTableDefs->Release();
  2087.  
  2088.     m_bNew = FALSE;
  2089.     m_bOpen = TRUE;
  2090. }
  2091.  
  2092. void CDaoTableDef::Open(LPCTSTR lpszName)
  2093. {
  2094.     ASSERT_VALID(this);
  2095.     ASSERT(lpszName != NULL);
  2096.  
  2097.     // Re-open is invalid
  2098.     if (IsOpen())
  2099.     {
  2100.         ASSERT(FALSE);
  2101.         return;
  2102.     }
  2103.  
  2104.     DAOTableDefs* pDAOTableDefs = NULL;
  2105.  
  2106.     TRY
  2107.     {
  2108.         DAO_CHECK(m_pDatabase->m_pDAODatabase->get_TableDefs(
  2109.             &pDAOTableDefs));
  2110.         DAO_CHECK(pDAOTableDefs->get_Item(
  2111.             COleVariant(lpszName, VT_BSTRT),&m_pDAOTableDef));
  2112.     }
  2113.     CATCH_ALL(e)
  2114.     {
  2115.         if (pDAOTableDefs != NULL)
  2116.             pDAOTableDefs->Release();
  2117.         THROW_LAST();
  2118.     }
  2119.     END_CATCH_ALL
  2120.  
  2121.     pDAOTableDefs->Release();
  2122.  
  2123.     m_bOpen = TRUE;
  2124.  
  2125.     // Add the tabledef to map of Open/New CDaoTableDefs
  2126.     m_pDatabase->m_mapTableDefs.SetAt(this, this);
  2127. }
  2128.  
  2129. void CDaoTableDef::Close()
  2130. {
  2131.     ASSERT_VALID(this);
  2132.  
  2133.     if (m_pDAOIndexes != NULL)
  2134.     {
  2135.         m_pDAOIndexes->Release();
  2136.         m_pDAOIndexes = NULL;
  2137.     }
  2138.  
  2139.     if (m_pDAOFields != NULL)
  2140.     {
  2141.         m_pDAOFields->Release();
  2142.         m_pDAOFields = NULL;
  2143.     }
  2144.  
  2145.     if (m_pDAOTableDef != NULL)
  2146.     {
  2147.         m_pDAOTableDef->Release();
  2148.         m_pDAOTableDef = NULL;
  2149.     }
  2150.  
  2151.     m_bOpen = FALSE;
  2152.     m_bNew = FALSE;
  2153.  
  2154.     // Remove the tabledef from the CDaoDatabase's map
  2155.     m_pDatabase->m_mapTableDefs.RemoveKey(this);
  2156. }
  2157.  
  2158. BOOL CDaoTableDef::CanUpdate()
  2159. {
  2160.     ASSERT_VALID(this);
  2161.     ASSERT(IsOpen());
  2162.     ASSERT(m_pDAOTableDef != NULL);
  2163.  
  2164.     short nUpdatable;
  2165.     DAO_CHECK(m_pDAOTableDef->get_Updatable(&nUpdatable));
  2166.     return nUpdatable == AFX_DAO_TRUE;
  2167. }
  2168.  
  2169. void CDaoTableDef::SetName(LPCTSTR lpszName)
  2170. {
  2171.     ASSERT_VALID(this);
  2172.     ASSERT(IsOpen() || m_bNew);
  2173.     ASSERT(m_pDAOTableDef != NULL);
  2174.  
  2175.     COleVariant var(lpszName, VT_BSTRT);
  2176.     DAO_CHECK(m_pDAOTableDef->put_Name(V_BSTR(&var)));
  2177. }
  2178.  
  2179. CString CDaoTableDef::GetName()
  2180. {
  2181.     ASSERT_VALID(this);
  2182.     ASSERT(IsOpen());
  2183.     ASSERT(m_pDAOTableDef != NULL);
  2184.  
  2185.     COleVariant var;
  2186.     DAO_CHECK(m_pDAOTableDef->get_Name(&V_BSTR(&var)));
  2187.     var.vt = VT_BSTR;
  2188.     return V_BSTRT(&var);
  2189. }
  2190.  
  2191. void CDaoTableDef::SetSourceTableName(LPCTSTR lpszSrcTableName)
  2192. {
  2193.     ASSERT_VALID(this);
  2194.     ASSERT(IsOpen() || m_bNew);
  2195.     ASSERT(m_pDAOTableDef != NULL);
  2196.  
  2197.     COleVariant var(lpszSrcTableName, VT_BSTRT);
  2198.     DAO_CHECK(m_pDAOTableDef->put_SourceTableName(
  2199.         V_BSTR(&var)));
  2200. }
  2201.  
  2202. CString CDaoTableDef::GetSourceTableName()
  2203. {
  2204.     ASSERT_VALID(this);
  2205.     ASSERT(IsOpen());
  2206.     ASSERT(m_pDAOTableDef != NULL);
  2207.  
  2208.     COleVariant var;
  2209.     DAO_CHECK(m_pDAOTableDef->get_SourceTableName(
  2210.         &V_BSTR(&var)));
  2211.     var.vt = VT_BSTR;
  2212.     return V_BSTRT(&var);
  2213. }
  2214.  
  2215. void CDaoTableDef::SetConnect(LPCTSTR lpszConnect)
  2216. {
  2217.     ASSERT_VALID(this);
  2218.     ASSERT(IsOpen() || m_bNew);
  2219.     ASSERT(m_pDAOTableDef != NULL);
  2220.  
  2221.     COleVariant var(lpszConnect, VT_BSTRT);
  2222.     DAO_CHECK(m_pDAOTableDef->put_Connect(V_BSTR(&var)));
  2223. }
  2224.  
  2225. CString CDaoTableDef::GetConnect()
  2226. {
  2227.     ASSERT_VALID(this);
  2228.     ASSERT(IsOpen());
  2229.     ASSERT(m_pDAOTableDef != NULL);
  2230.  
  2231.     COleVariant var;
  2232.     DAO_CHECK(m_pDAOTableDef->get_Connect(&V_BSTR(&var)));
  2233.     var.vt = VT_BSTR;
  2234.     return V_BSTRT(&var);
  2235. }
  2236.  
  2237. void CDaoTableDef::SetAttributes(long lAttributes)
  2238. {
  2239.     ASSERT_VALID(this);
  2240.     ASSERT(IsOpen() || m_bNew);
  2241.     ASSERT(m_pDAOTableDef != NULL);
  2242.  
  2243.     DAO_CHECK(m_pDAOTableDef->put_Attributes(lAttributes));
  2244. }
  2245.  
  2246. long CDaoTableDef::GetAttributes()
  2247. {
  2248.     ASSERT_VALID(this);
  2249.     ASSERT(IsOpen());
  2250.     ASSERT(m_pDAOTableDef != NULL);
  2251.  
  2252.     long lAttributes;
  2253.     DAO_CHECK(m_pDAOTableDef->get_Attributes(&lAttributes));
  2254.     return lAttributes;
  2255. }
  2256.  
  2257. COleDateTime CDaoTableDef::GetDateCreated()
  2258. {
  2259.     ASSERT_VALID(this);
  2260.     ASSERT(IsOpen());
  2261.     ASSERT(m_pDAOTableDef != NULL);
  2262.  
  2263.     COleVariant varDate;
  2264.     DAO_CHECK(m_pDAOTableDef->get_DateCreated(&varDate));
  2265.     return varDate.date;
  2266. }
  2267.  
  2268. COleDateTime CDaoTableDef::GetDateLastUpdated()
  2269. {
  2270.     ASSERT_VALID(this);
  2271.     ASSERT(IsOpen());
  2272.     ASSERT(m_pDAOTableDef != NULL);
  2273.  
  2274.     COleVariant varDate;
  2275.     DAO_CHECK(m_pDAOTableDef->get_LastUpdated(&varDate));
  2276.     return varDate.date;
  2277. }
  2278.  
  2279. void CDaoTableDef::SetValidationRule(
  2280.     LPCTSTR lpszValidationRule)
  2281. {
  2282.     ASSERT_VALID(this);
  2283.     ASSERT(IsOpen() || m_bNew);
  2284.     ASSERT(m_pDAOTableDef != NULL);
  2285.  
  2286.     COleVariant var(lpszValidationRule, VT_BSTRT);
  2287.     DAO_CHECK(m_pDAOTableDef->put_ValidationRule(
  2288.         V_BSTR(&var)));
  2289. }
  2290.  
  2291. CString CDaoTableDef::GetValidationRule()
  2292. {
  2293.     ASSERT_VALID(this);
  2294.     ASSERT(IsOpen());
  2295.     ASSERT(m_pDAOTableDef != NULL);
  2296.  
  2297.     COleVariant var;
  2298.     DAO_CHECK(m_pDAOTableDef->get_ValidationRule(
  2299.         &V_BSTR(&var)));
  2300.     var.vt = VT_BSTR;
  2301.     return V_BSTRT(&var);
  2302. }
  2303.  
  2304. void CDaoTableDef::SetValidationText(
  2305.     LPCTSTR lpszValidationText)
  2306. {
  2307.     ASSERT_VALID(this);
  2308.     ASSERT(IsOpen() || m_bNew);
  2309.     ASSERT(m_pDAOTableDef != NULL);
  2310.  
  2311.     COleVariant var(lpszValidationText, VT_BSTRT);
  2312.     DAO_CHECK(m_pDAOTableDef->put_ValidationText(
  2313.         V_BSTR(&var)));
  2314. }
  2315.  
  2316. CString CDaoTableDef::GetValidationText()
  2317. {
  2318.     ASSERT_VALID(this);
  2319.     ASSERT(IsOpen());
  2320.     ASSERT(m_pDAOTableDef != NULL);
  2321.  
  2322.     COleVariant var;
  2323.     DAO_CHECK(m_pDAOTableDef->get_ValidationText(
  2324.         &V_BSTR(&var)));
  2325.     var.vt = VT_BSTR;
  2326.     return V_BSTRT(&var);
  2327. }
  2328.  
  2329. long CDaoTableDef::GetRecordCount()
  2330. {
  2331.     ASSERT_VALID(this);
  2332.     ASSERT(IsOpen());
  2333.     ASSERT(m_pDAOTableDef != NULL);
  2334.  
  2335.     long lRecordCount;
  2336.     DAO_CHECK(m_pDAOTableDef->get_RecordCount(&lRecordCount));
  2337.     return lRecordCount;
  2338. }
  2339.  
  2340. void CDaoTableDef::CreateField(LPCTSTR lpszName, short nType, long lSize,
  2341.     long lAttributes)
  2342. {
  2343.     ASSERT_VALID(this);
  2344.  
  2345.     CDaoFieldInfo fieldinfo;
  2346.  
  2347.     // Initialize everything so only correct properties will be set
  2348.     fieldinfo.m_strName = lpszName;
  2349.     fieldinfo.m_nType = nType;
  2350.     fieldinfo.m_lSize = lSize;
  2351.     fieldinfo.m_lAttributes = lAttributes;
  2352.     fieldinfo.m_nOrdinalPosition = 0;
  2353.     fieldinfo.m_bRequired = FALSE;
  2354.     fieldinfo.m_bAllowZeroLength = FALSE;
  2355.     fieldinfo.m_lCollatingOrder = 0;
  2356.  
  2357.     CreateField(fieldinfo);
  2358. }
  2359.  
  2360. void CDaoTableDef::CreateField(CDaoFieldInfo& fieldinfo)
  2361. {
  2362.     ASSERT_VALID(this);
  2363.  
  2364.     DAOField* pDAOField;
  2365.  
  2366.     // Create the DAO field object (setting basic properties)
  2367.     DAO_CHECK(m_pDAOTableDef->CreateField(
  2368.         COleVariant(fieldinfo.m_strName, VT_BSTRT),
  2369.         COleVariant(fieldinfo.m_nType),
  2370.         COleVariant(fieldinfo.m_lSize), &pDAOField));
  2371.  
  2372.     TRY
  2373.     {
  2374.         // Basic properties already set, so set the rest
  2375.         AfxSetFieldInfo(pDAOField, fieldinfo);
  2376.  
  2377.         // Append the field object to the fields collection
  2378.         if (m_pDAOFields == NULL)
  2379.             InitFieldsCollection();
  2380.         DAO_CHECK(m_pDAOFields->Append(pDAOField));
  2381.     }
  2382.     CATCH_ALL(e)
  2383.     {
  2384.         pDAOField->Release();
  2385.         THROW_LAST();
  2386.     }
  2387.     END_CATCH_ALL
  2388.  
  2389.     pDAOField->Release();
  2390. }
  2391.  
  2392. void CDaoTableDef::DeleteField(LPCTSTR lpszName)
  2393. {
  2394.     ASSERT_VALID(this);
  2395.  
  2396.     ASSERT(lpszName != NULL);
  2397.  
  2398.     if (m_pDAOFields == NULL)
  2399.         InitFieldsCollection();
  2400.  
  2401.     COleVariant var(lpszName, VT_BSTRT);
  2402.     DAO_CHECK(m_pDAOFields->Delete(V_BSTR(&var)));
  2403. }
  2404.  
  2405. void CDaoTableDef::DeleteField(int nIndex)
  2406. {
  2407.     ASSERT_VALID(this);
  2408.  
  2409.     CDaoFieldInfo fieldinfo;
  2410.     GetFieldInfo(nIndex, fieldinfo, AFX_DAO_PRIMARY_INFO);
  2411.     DeleteField((LPCTSTR)fieldinfo.m_strName);
  2412. }
  2413.  
  2414. void CDaoTableDef::CreateIndex(CDaoIndexInfo& indexinfo)
  2415. {
  2416.     ASSERT_VALID(this);
  2417.  
  2418.     DAOIndex* pDAOIndex;
  2419.  
  2420.     DAO_CHECK(m_pDAOTableDef->CreateIndex(
  2421.         COleVariant(indexinfo.m_strName, VT_BSTRT), &pDAOIndex));
  2422.  
  2423.     TRY
  2424.     {
  2425.         // Set the index info
  2426.         AfxSetIndexInfo(pDAOIndex, indexinfo);
  2427.  
  2428.         // Append the field object to the fields collection
  2429.         if (m_pDAOIndexes == NULL)
  2430.             InitIndexesCollection();
  2431.         DAO_CHECK(m_pDAOIndexes->Append(pDAOIndex));
  2432.     }
  2433.     CATCH_ALL(e)
  2434.     {
  2435.         pDAOIndex->Release();
  2436.         THROW_LAST();
  2437.     }
  2438.     END_CATCH_ALL
  2439.  
  2440.     pDAOIndex->Release();
  2441. }
  2442.  
  2443. void CDaoTableDef::DeleteIndex(LPCTSTR lpszName)
  2444. {
  2445.     ASSERT_VALID(this);
  2446.     ASSERT(lpszName != NULL);
  2447.  
  2448.     if (m_pDAOIndexes == NULL)
  2449.         InitIndexesCollection();
  2450.  
  2451.     COleVariant var(lpszName, VT_BSTRT);
  2452.     DAO_CHECK(m_pDAOIndexes->Delete(V_BSTR(&var)));
  2453. }
  2454.  
  2455. void CDaoTableDef::DeleteIndex(int nIndex)
  2456. {
  2457.     ASSERT_VALID(this);
  2458.  
  2459.     CDaoIndexInfo indexinfo;
  2460.     GetIndexInfo(nIndex, indexinfo, AFX_DAO_PRIMARY_INFO);
  2461.     DeleteIndex((LPCTSTR)indexinfo.m_strName);
  2462. }
  2463.  
  2464. short CDaoTableDef::GetFieldCount()
  2465. {
  2466.     ASSERT_VALID(this);
  2467.  
  2468.     short nFields;
  2469.  
  2470.     if (m_pDAOFields == NULL)
  2471.         InitFieldsCollection();
  2472.  
  2473.     DAO_CHECK(m_pDAOFields->get_Count(&nFields));
  2474.     return nFields;
  2475. }
  2476.  
  2477. void CDaoTableDef::GetFieldInfo(int nIndex, CDaoFieldInfo& fieldinfo,
  2478.     DWORD dwInfoOptions)
  2479. {
  2480.     ASSERT_VALID(this);
  2481.  
  2482.     if (m_pDAOFields == NULL)
  2483.         InitFieldsCollection();
  2484.  
  2485.     // Get DAOField object and fill in field info struct
  2486.     DAOField* pDAOField;
  2487.     DAO_CHECK(m_pDAOFields->get_Item(
  2488.         COleVariant((long)nIndex), &pDAOField));
  2489.     AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
  2490.  
  2491.     // Clean up
  2492.     pDAOField->Release();
  2493. }
  2494.  
  2495. void CDaoTableDef::GetFieldInfo(LPCTSTR lpszName,
  2496.     CDaoFieldInfo& fieldinfo, DWORD dwInfoOptions)
  2497. {
  2498.     ASSERT_VALID(this);
  2499.  
  2500.     if (m_pDAOFields == NULL)
  2501.         InitFieldsCollection();
  2502.  
  2503.     // Get DAOField object and fill in field info struct
  2504.     DAOField* pDAOField;
  2505.     DAO_CHECK(m_pDAOFields->get_Item(
  2506.         COleVariant(lpszName, VT_BSTRT), &pDAOField));
  2507.     AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
  2508.  
  2509.     // Clean up
  2510.     pDAOField->Release();
  2511. }
  2512.  
  2513. short CDaoTableDef::GetIndexCount()
  2514. {
  2515.     ASSERT_VALID(this);
  2516.  
  2517.     short nIndexes;
  2518.  
  2519.     if (m_pDAOIndexes == NULL)
  2520.         InitIndexesCollection();
  2521.  
  2522.     DAO_CHECK(m_pDAOIndexes->get_Count(&nIndexes));
  2523.     return nIndexes;
  2524. }
  2525.  
  2526. void CDaoTableDef::GetIndexInfo(int nIndex, CDaoIndexInfo& indexinfo,
  2527.     DWORD dwInfoOptions)
  2528. {
  2529.     ASSERT_VALID(this);
  2530.  
  2531.     if (m_pDAOIndexes == NULL)
  2532.         InitIndexesCollection();
  2533.  
  2534.     // Get DAOField object and fill in field info struct
  2535.     DAOIndex* pDAOIndex;
  2536.     DAO_CHECK(m_pDAOIndexes->get_Item(
  2537.         COleVariant((long)nIndex), &pDAOIndex));
  2538.     AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
  2539.  
  2540.     // Clean up
  2541.     pDAOIndex->Release();
  2542. }
  2543.  
  2544. void CDaoTableDef::GetIndexInfo(LPCTSTR lpszName,
  2545.     CDaoIndexInfo& indexinfo, DWORD dwInfoOptions)
  2546. {
  2547.     ASSERT_VALID(this);
  2548.  
  2549.     if (m_pDAOIndexes == NULL)
  2550.         InitIndexesCollection();
  2551.  
  2552.     // Get DAOField object and fill in field info struct
  2553.     DAOIndex* pDAOIndex;
  2554.     DAO_CHECK(m_pDAOIndexes->get_Item(
  2555.         COleVariant(lpszName, VT_BSTRT), &pDAOIndex));
  2556.     AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
  2557.  
  2558.     // Clean up
  2559.     pDAOIndex->Release();
  2560. }
  2561.  
  2562. void CDaoTableDef::RefreshLink()
  2563. {
  2564.     ASSERT_VALID(this);
  2565.     ASSERT(IsOpen());
  2566.     ASSERT(m_pDAOTableDef != NULL);
  2567.  
  2568.     DAO_CHECK(m_pDAOTableDef->RefreshLink());
  2569. }
  2570.  
  2571. //Implementation functions
  2572. void CDaoTableDef::InitFieldsCollection()
  2573. {
  2574.     ASSERT_VALID(this);
  2575.  
  2576.     DAO_CHECK(m_pDAOTableDef->get_Fields(&m_pDAOFields));
  2577. }
  2578.  
  2579. void CDaoTableDef::InitIndexesCollection()
  2580. {
  2581.     ASSERT_VALID(this);
  2582.  
  2583.     DAO_CHECK(m_pDAOTableDef->get_Indexes(&m_pDAOIndexes));
  2584. }
  2585.  
  2586. void CDaoTableDef::ThrowDaoException(int nAfxDaoError)
  2587. {
  2588.     ASSERT_VALID(this);
  2589.  
  2590.     AfxThrowDaoException(nAfxDaoError);
  2591. }
  2592.  
  2593. #ifdef _DEBUG
  2594. void CDaoTableDef::AssertValid() const
  2595. {
  2596.     CObject::AssertValid();
  2597. }
  2598.  
  2599. void CDaoTableDef::Dump(CDumpContext& dc) const
  2600. {
  2601.     ASSERT_VALID(this);
  2602.  
  2603.     CObject::Dump(dc);
  2604.  
  2605.     dc << "m_bOpen = " << m_bOpen;
  2606.     dc << "\nm_bNew = " << m_bNew;
  2607.  
  2608.     dc << "\n";
  2609. }
  2610. #endif //_DEBUG
  2611.  
  2612. //////////////////////////////////////////////////////////////////////////
  2613. // CDaoQueryDef
  2614. IMPLEMENT_DYNAMIC(CDaoQueryDef, CObject)
  2615.  
  2616. CDaoQueryDef::CDaoQueryDef(CDaoDatabase* pDatabase)
  2617. {
  2618.     m_bOpen = FALSE;
  2619.     m_bNew = FALSE;
  2620.  
  2621.     m_pDatabase = pDatabase;
  2622.     m_pDAOQueryDef = NULL;
  2623.     m_pDAOParameters = NULL;
  2624.     m_pDAOFields = NULL;
  2625. }
  2626.  
  2627. CDaoQueryDef::~CDaoQueryDef()
  2628. {
  2629.     if (IsOpen())
  2630.         Close();
  2631.     else if (m_bNew)
  2632.     {
  2633.         // Remove the querydef from the CDaoDatabase's map
  2634.         m_pDatabase->m_mapQueryDefs.RemoveKey(this);
  2635.     }
  2636. }
  2637.  
  2638. void CDaoQueryDef::Create(LPCTSTR lpszName, LPCTSTR lpszSQL)
  2639. {
  2640.     ASSERT_VALID(this);
  2641.     ASSERT(!IsOpen());
  2642.  
  2643.     // Create a temp querydef if lpszName is NULL or empty string
  2644.     if (lpszName == NULL || *lpszName == '\0')
  2645.     {
  2646.         DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateQueryDef(
  2647.             COleVariant(_T(""), VT_BSTRT),
  2648.             COleVariant(lpszSQL, VT_BSTRT),
  2649.             &m_pDAOQueryDef));
  2650.         m_bOpen = TRUE;
  2651.     }
  2652.     else
  2653.     {
  2654.         // Create a template querydef
  2655.         // (preventing automatic append to QueryDefs collection)
  2656.         DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateQueryDef(
  2657.             _afxOptionalVariant, _afxOptionalVariant, &m_pDAOQueryDef));
  2658.         m_bNew = TRUE;
  2659.  
  2660.         // Now set the name and SQL if necessary
  2661.         SetName(lpszName);
  2662.         if (lpszSQL != NULL)
  2663.             SetSQL(lpszSQL);
  2664.     }
  2665.  
  2666.     // Add the querydef to map of Open/New CDaoQueryDefs
  2667.     m_pDatabase->m_mapQueryDefs.SetAt(this, this);
  2668. }
  2669.  
  2670. void CDaoQueryDef::Append()
  2671. {
  2672.     ASSERT_VALID(this);
  2673.     ASSERT(m_bNew);
  2674.     ASSERT(m_pDAOQueryDef != NULL);
  2675.  
  2676.     DAOQueryDefs* pDAOQueryDefs;
  2677.     DAO_CHECK(m_pDatabase->m_pDAODatabase->get_QueryDefs(
  2678.         &pDAOQueryDefs));
  2679.  
  2680.     TRY
  2681.     {
  2682.         DAO_CHECK(pDAOQueryDefs->Append(m_pDAOQueryDef));
  2683.     }
  2684.     CATCH_ALL(e)
  2685.     {
  2686.         pDAOQueryDefs->Release();
  2687.         THROW_LAST();
  2688.     }
  2689.     END_CATCH_ALL
  2690.  
  2691.     pDAOQueryDefs->Release();
  2692.  
  2693.     m_bNew = FALSE;
  2694.     m_bOpen = TRUE;
  2695. }
  2696.  
  2697. // Open a pre-defined query or create a temp query
  2698. void CDaoQueryDef::Open(LPCTSTR lpszName)
  2699. {
  2700.     ASSERT_VALID(this);
  2701.     ASSERT(!m_bNew);
  2702.  
  2703.     // Re-open is not allowed
  2704.     if (IsOpen())
  2705.     {
  2706.         ASSERT(FALSE);
  2707.         return;
  2708.     }
  2709.  
  2710.     // Null lpszName implies create a temp query
  2711.     if (lpszName == NULL)
  2712.     {
  2713.         DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateQueryDef(
  2714.             COleVariant(_T(""), VT_BSTRT), _afxOptionalVariant, &m_pDAOQueryDef));
  2715.     }
  2716.     else
  2717.     {
  2718.         COleVariant varName(lpszName, VT_BSTRT);
  2719.         DAO_CHECK(m_pDatabase->m_pDAODatabase->OpenQueryDef(
  2720.             V_BSTR(&varName), &m_pDAOQueryDef));
  2721.     }
  2722.  
  2723.     m_bOpen = TRUE;
  2724.  
  2725.     // Add the querydef to map of Open/New CDaoQueryDefs
  2726.     m_pDatabase->m_mapQueryDefs.SetAt(this, this);
  2727. }
  2728.  
  2729. void CDaoQueryDef::Close()
  2730. {
  2731.     ASSERT_VALID(this);
  2732.  
  2733.     if (m_pDAOParameters != NULL)
  2734.     {
  2735.         m_pDAOParameters->Release();
  2736.         m_pDAOParameters = NULL;
  2737.     }
  2738.  
  2739.     if (m_pDAOFields != NULL)
  2740.     {
  2741.         m_pDAOFields->Release();
  2742.         m_pDAOFields = NULL;
  2743.     }
  2744.  
  2745.     if (m_pDAOQueryDef != NULL)
  2746.     {
  2747.         // DAO Close is a no op, but call it anyway
  2748.         DAO_TRACE(m_pDAOQueryDef->Close());
  2749.         m_pDAOQueryDef->Release();
  2750.         m_pDAOQueryDef = NULL;
  2751.     }
  2752.  
  2753.     m_bOpen = FALSE;
  2754.     m_bNew = FALSE;
  2755.  
  2756.     // Remove the querydef from the CDaoDatabase's map
  2757.     m_pDatabase->m_mapQueryDefs.RemoveKey(this);
  2758. }
  2759.  
  2760. BOOL CDaoQueryDef::CanUpdate()
  2761. {
  2762.     ASSERT_VALID(this);
  2763.     ASSERT(IsOpen());
  2764.  
  2765.     short nUpdatable;
  2766.     DAO_CHECK(m_pDAOQueryDef->get_Updatable(&nUpdatable));
  2767.     return nUpdatable == AFX_DAO_TRUE;
  2768. }
  2769.  
  2770. CString CDaoQueryDef::GetName()
  2771. {
  2772.     ASSERT_VALID(this);
  2773.     ASSERT(IsOpen());
  2774.  
  2775.     COleVariant var;
  2776.     DAO_CHECK(m_pDAOQueryDef->get_Name(&V_BSTR(&var)));
  2777.     var.vt = VT_BSTR;
  2778.     return V_BSTRT(&var);
  2779. }
  2780.  
  2781. void CDaoQueryDef::SetName(LPCTSTR lpszName)
  2782. {
  2783.     ASSERT_VALID(this);
  2784.     ASSERT(IsOpen() || m_bNew);
  2785.  
  2786.     COleVariant var(lpszName, VT_BSTRT);
  2787.     DAO_CHECK(m_pDAOQueryDef->put_Name(V_BSTR(&var)));
  2788. }
  2789.  
  2790. CString CDaoQueryDef::GetSQL()
  2791. {
  2792.     ASSERT_VALID(this);
  2793.     ASSERT(IsOpen());
  2794.  
  2795.     COleVariant var;
  2796.     DAO_CHECK(m_pDAOQueryDef->get_SQL(&V_BSTR(&var)));
  2797.     var.vt = VT_BSTR;
  2798.     return V_BSTRT(&var);
  2799. }
  2800.  
  2801. void CDaoQueryDef::SetSQL(LPCTSTR lpszSQL)
  2802. {
  2803.     ASSERT_VALID(this);
  2804.     ASSERT(IsOpen() || m_bNew);
  2805.  
  2806.     COleVariant var(lpszSQL, VT_BSTRT);
  2807.     DAO_CHECK(m_pDAOQueryDef->put_SQL(V_BSTR(&var)));
  2808. }
  2809.  
  2810. short CDaoQueryDef::GetType()
  2811. {
  2812.     ASSERT_VALID(this);
  2813.     ASSERT(IsOpen());
  2814.  
  2815.     short nType;
  2816.     DAO_CHECK(m_pDAOQueryDef->get_Type(&nType));
  2817.     return nType;
  2818. }
  2819.  
  2820. COleDateTime CDaoQueryDef::GetDateCreated()
  2821. {
  2822.     ASSERT_VALID(this);
  2823.     ASSERT(IsOpen());
  2824.  
  2825.     COleVariant varDate;
  2826.     DAO_CHECK(m_pDAOQueryDef->get_DateCreated(&varDate));
  2827.     return varDate.date;
  2828. }
  2829.  
  2830. COleDateTime CDaoQueryDef::GetDateLastUpdated()
  2831. {
  2832.     ASSERT_VALID(this);
  2833.     ASSERT(IsOpen());
  2834.  
  2835.     COleVariant varDate;
  2836.     DAO_CHECK(m_pDAOQueryDef->get_LastUpdated(&varDate));
  2837.     return varDate.date;
  2838. }
  2839.  
  2840. CString CDaoQueryDef::GetConnect()
  2841. {
  2842.     ASSERT_VALID(this);
  2843.     ASSERT(IsOpen());
  2844.  
  2845.     COleVariant var;
  2846.     DAO_CHECK(m_pDAOQueryDef->get_Connect(&V_BSTR(&var)));
  2847.     var.vt = VT_BSTR;
  2848.     return V_BSTRT(&var);
  2849. }
  2850.  
  2851. void CDaoQueryDef::SetConnect(LPCTSTR lpszConnect)
  2852. {
  2853.     ASSERT_VALID(this);
  2854.     ASSERT(IsOpen() || m_bNew);
  2855.  
  2856.     COleVariant var(lpszConnect, VT_BSTRT);
  2857.     DAO_CHECK(m_pDAOQueryDef->put_Connect(V_BSTR(&var)));
  2858. }
  2859.  
  2860. short CDaoQueryDef::GetODBCTimeout()
  2861. {
  2862.     ASSERT_VALID(this);
  2863.     ASSERT(IsOpen());
  2864.  
  2865.     short nTimeout;
  2866.     DAO_CHECK(m_pDAOQueryDef->get_ODBCTimeout(&nTimeout));
  2867.     return nTimeout;
  2868. }
  2869.  
  2870. void CDaoQueryDef::SetODBCTimeout(short nODBCTimeout)
  2871. {
  2872.     ASSERT_VALID(this);
  2873.     ASSERT(IsOpen() || m_bNew);
  2874.  
  2875.     DAO_CHECK(m_pDAOQueryDef->put_ODBCTimeout(nODBCTimeout));
  2876. }
  2877.  
  2878. BOOL CDaoQueryDef::GetReturnsRecords()
  2879. {
  2880.     ASSERT_VALID(this);
  2881.     ASSERT(IsOpen());
  2882.  
  2883.     short nReturnsRecords;
  2884.     DAO_CHECK(m_pDAOQueryDef->get_ReturnsRecords(&nReturnsRecords));
  2885.     return nReturnsRecords == AFX_DAO_TRUE;
  2886. }
  2887.  
  2888. void CDaoQueryDef::SetReturnsRecords(BOOL bReturnsRecords)
  2889. {
  2890.     ASSERT_VALID(this);
  2891.     ASSERT(IsOpen() || m_bNew);
  2892.  
  2893.     DAO_CHECK(m_pDAOQueryDef->put_ReturnsRecords(
  2894.         (short)(bReturnsRecords ? AFX_DAO_TRUE : AFX_DAO_FALSE)));
  2895. }
  2896.  
  2897. long CDaoQueryDef::GetRecordsAffected()
  2898. {
  2899.     ASSERT_VALID(this);
  2900.     ASSERT(IsOpen());
  2901.  
  2902.     long lRecordsAffected;
  2903.     DAO_CHECK(m_pDAOQueryDef->get_RecordsAffected(&lRecordsAffected));
  2904.     return lRecordsAffected;
  2905. }
  2906.  
  2907. void CDaoQueryDef::Execute(int nOptions)
  2908. {
  2909.     ASSERT_VALID(this);
  2910.     ASSERT(m_pDAOQueryDef != NULL);
  2911.  
  2912.     DAO_CHECK(m_pDAOQueryDef->Execute(COleVariant((long)nOptions)));
  2913. }
  2914.  
  2915. COleVariant CDaoQueryDef::GetParamValue(LPCTSTR lpszName)
  2916. {
  2917.     ASSERT_VALID(this);
  2918.     ASSERT(IsOpen());
  2919.     ASSERT(m_pDAOQueryDef != NULL);
  2920.  
  2921.     if (m_pDAOParameters == NULL)
  2922.         InitParametersCollection();
  2923.  
  2924.     DAOParameter* pDAOParameter = NULL;
  2925.     COleVariant var;
  2926.  
  2927.     TRY
  2928.     {
  2929.         DAO_CHECK(m_pDAOParameters->get_Item(
  2930.             COleVariant(lpszName, VT_BSTRT), &pDAOParameter));
  2931.         DAO_CHECK(pDAOParameter->get_Value(&var));
  2932.     }
  2933.     CATCH_ALL(e)
  2934.     {
  2935.         if (pDAOParameter != NULL)
  2936.             pDAOParameter->Release();
  2937.         THROW_LAST();
  2938.     }
  2939.     END_CATCH_ALL
  2940.  
  2941.     pDAOParameter->Release();
  2942.     return var;
  2943. }
  2944.  
  2945. COleVariant CDaoQueryDef::GetParamValue(int nIndex)
  2946. {
  2947.     ASSERT_VALID(this);
  2948.     ASSERT(IsOpen());
  2949.     ASSERT(m_pDAOQueryDef != NULL);
  2950.  
  2951.     if (m_pDAOParameters == NULL)
  2952.         InitParametersCollection();
  2953.  
  2954.     DAOParameter* pDAOParameter = NULL;
  2955.     COleVariant var;
  2956.  
  2957.     TRY
  2958.     {
  2959.         DAO_CHECK(m_pDAOParameters->get_Item(
  2960.             COleVariant((long)nIndex), &pDAOParameter));
  2961.         DAO_CHECK(pDAOParameter->get_Value(&var));
  2962.     }
  2963.     CATCH_ALL(e)
  2964.     {
  2965.         if (pDAOParameter != NULL)
  2966.             pDAOParameter->Release();
  2967.         THROW_LAST();
  2968.     }
  2969.     END_CATCH_ALL
  2970.  
  2971.     pDAOParameter->Release();
  2972.     return var;
  2973. }
  2974.  
  2975. void CDaoQueryDef::SetParamValue(LPCTSTR lpszName,
  2976.     const COleVariant& varValue)
  2977. {
  2978.     ASSERT_VALID(this);
  2979.     ASSERT(IsOpen() || m_bNew);
  2980.     ASSERT(m_pDAOQueryDef != NULL);
  2981.  
  2982.     if (m_pDAOParameters == NULL)
  2983.         InitParametersCollection();
  2984.  
  2985.     DAOParameter* pDAOParameter = NULL;
  2986.  
  2987.     TRY
  2988.     {
  2989.         DAO_CHECK(m_pDAOParameters->get_Item(
  2990.             COleVariant(lpszName, VT_BSTRT), &pDAOParameter));
  2991.         DAO_CHECK(pDAOParameter->put_Value(varValue));
  2992.     }
  2993.     CATCH_ALL(e)
  2994.     {
  2995.         if (pDAOParameter != NULL)
  2996.             pDAOParameter->Release();
  2997.         THROW_LAST();
  2998.     }
  2999.     END_CATCH_ALL
  3000.  
  3001.     pDAOParameter->Release();
  3002. }
  3003.  
  3004. void CDaoQueryDef::SetParamValue(int nIndex,
  3005.     const COleVariant& varValue)
  3006. {
  3007.     ASSERT_VALID(this);
  3008.     ASSERT(IsOpen() || m_bNew);
  3009.     ASSERT(m_pDAOQueryDef != NULL);
  3010.  
  3011.     if (m_pDAOParameters == NULL)
  3012.         InitParametersCollection();
  3013.  
  3014.     DAOParameter* pDAOParameter = NULL;
  3015.  
  3016.     TRY
  3017.     {
  3018.         DAO_CHECK(m_pDAOParameters->get_Item(
  3019.             COleVariant((long)nIndex), &pDAOParameter));
  3020.         DAO_CHECK(pDAOParameter->put_Value(varValue));
  3021.     }
  3022.     CATCH_ALL(e)
  3023.     {
  3024.         if (pDAOParameter != NULL)
  3025.             pDAOParameter->Release();
  3026.         THROW_LAST();
  3027.     }
  3028.     END_CATCH_ALL
  3029.  
  3030.     pDAOParameter->Release();
  3031. }
  3032.  
  3033. void CDaoQueryDef::SetParamValueNull(LPCTSTR lpszName)
  3034. {
  3035.     ASSERT_VALID(this);
  3036.  
  3037.     SetParamValue(lpszName, _afxNullVariant);
  3038. }
  3039.  
  3040. void CDaoQueryDef::SetParamValueNull(int nIndex)
  3041. {
  3042.     ASSERT_VALID(this);
  3043.  
  3044.     SetParamValue(nIndex, _afxNullVariant);
  3045. }
  3046.  
  3047. short CDaoQueryDef::GetFieldCount()
  3048. {
  3049.     ASSERT_VALID(this);
  3050.  
  3051.     short nFields;
  3052.  
  3053.     if (m_pDAOFields == NULL)
  3054.         InitFieldsCollection();
  3055.  
  3056.     DAO_CHECK(m_pDAOFields->get_Count(&nFields));
  3057.     return nFields;
  3058. }
  3059.  
  3060. void CDaoQueryDef::GetFieldInfo(int nIndex, CDaoFieldInfo& fieldinfo,
  3061.     DWORD dwInfoOptions)
  3062. {
  3063.     ASSERT_VALID(this);
  3064.  
  3065.     if (m_pDAOFields == NULL)
  3066.         InitFieldsCollection();
  3067.  
  3068.     // Get DAOField object and fill in field info struct
  3069.     DAOField* pDAOField;
  3070.     DAO_CHECK(m_pDAOFields->get_Item(
  3071.         COleVariant((long)nIndex), &pDAOField));
  3072.     AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
  3073.  
  3074.     // Clean up
  3075.     pDAOField->Release();
  3076. }
  3077.  
  3078. void CDaoQueryDef::GetFieldInfo(LPCTSTR lpszName,
  3079.     CDaoFieldInfo& fieldinfo, DWORD dwInfoOptions)
  3080. {
  3081.     ASSERT_VALID(this);
  3082.  
  3083.     if (m_pDAOFields == NULL)
  3084.         InitFieldsCollection();
  3085.  
  3086.     // Get DAOField object and fill in field info struct
  3087.     DAOField* pDAOField;
  3088.     DAO_CHECK(m_pDAOFields->get_Item(
  3089.         COleVariant(lpszName, VT_BSTRT), &pDAOField));
  3090.     AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
  3091.  
  3092.     // Clean up
  3093.     pDAOField->Release();
  3094. }
  3095.  
  3096. short CDaoQueryDef::GetParameterCount()
  3097. {
  3098.     ASSERT_VALID(this);
  3099.  
  3100.     short nParameters;
  3101.  
  3102.     if (m_pDAOParameters == NULL)
  3103.         InitParametersCollection();
  3104.  
  3105.     DAO_CHECK(m_pDAOParameters->get_Count(&nParameters));
  3106.     return nParameters;
  3107. }
  3108.  
  3109. void CDaoQueryDef::GetParameterInfo(int nIndex,
  3110.     CDaoParameterInfo& paraminfo, DWORD dwInfoOptions)
  3111. {
  3112.     ASSERT_VALID(this);
  3113.  
  3114.     if (m_pDAOParameters == NULL)
  3115.         InitParametersCollection();
  3116.  
  3117.     // Get DAOParameter object and fill in parameter info struct
  3118.     DAOParameter* pDAOParameter;
  3119.     DAO_CHECK(m_pDAOParameters->get_Item(
  3120.         COleVariant((long)nIndex), &pDAOParameter));
  3121.     FillParameterInfo(pDAOParameter, paraminfo, dwInfoOptions);
  3122.  
  3123.     // Clean up
  3124.     pDAOParameter->Release();
  3125. }
  3126.  
  3127. void CDaoQueryDef::GetParameterInfo(LPCTSTR lpszName,
  3128.     CDaoParameterInfo& paraminfo, DWORD dwInfoOptions)
  3129. {
  3130.     ASSERT_VALID(this);
  3131.  
  3132.     if (m_pDAOParameters == NULL)
  3133.         InitParametersCollection();
  3134.  
  3135.     // Get DAOParameter object and fill in parameter info struct
  3136.     DAOParameter* pDAOParameter;
  3137.     DAO_CHECK(m_pDAOParameters->get_Item(
  3138.         COleVariant(lpszName, VT_BSTRT), &pDAOParameter));
  3139.     FillParameterInfo(pDAOParameter, paraminfo, dwInfoOptions);
  3140.  
  3141.     // Clean up
  3142.     pDAOParameter->Release();
  3143. }
  3144.  
  3145. //Implementation functions
  3146. void CDaoQueryDef::InitFieldsCollection()
  3147. {
  3148.     ASSERT_VALID(this);
  3149.  
  3150.     DAO_CHECK(m_pDAOQueryDef->get_Fields(&m_pDAOFields));
  3151. }
  3152.  
  3153. void CDaoQueryDef::InitParametersCollection()
  3154. {
  3155.     ASSERT_VALID(this);
  3156.  
  3157.     DAO_CHECK(m_pDAOQueryDef->get_Parameters(&m_pDAOParameters));
  3158. }
  3159.  
  3160. void CDaoQueryDef::FillParameterInfo(DAOParameter* pDAOParameter,
  3161.     CDaoParameterInfo& paraminfo, DWORD dwOptions)
  3162. {
  3163.     ASSERT_VALID(this);
  3164.     ASSERT(pDAOParameter != NULL);
  3165.     ASSERT(dwOptions != NULL);
  3166.  
  3167.     COleVariant var;
  3168.  
  3169.     if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  3170.     {
  3171.         // All parameter info is basic info
  3172.         DAO_CHECK(pDAOParameter->get_Name(&V_BSTR(&var)));
  3173.         var.vt = VT_BSTR;
  3174.         paraminfo.m_strName = V_BSTRT(&var);
  3175.         var.Clear();
  3176.  
  3177.         TCHAR* pch = paraminfo.m_strName.GetBuffer(0);
  3178.         int nLength = lstrlen(pch);
  3179.         if (nLength > 0 && *pch == '[' && *(pch + nLength -1) == ']')
  3180.         {
  3181.             *(pch + nLength - 1) = 0;  // remove last bracket.
  3182.             lstrcpy(pch, pch + 1);
  3183.         }
  3184.  
  3185.         paraminfo.m_strName.ReleaseBuffer(-1);
  3186.  
  3187.         DAO_CHECK(pDAOParameter->get_Type(
  3188.             Â¶minfo.m_nType));
  3189.  
  3190.         DAO_CHECK(pDAOParameter->get_Value(
  3191.             Â¶minfo.m_varValue));
  3192.     }
  3193. }
  3194.  
  3195. void CDaoQueryDef::ThrowDaoException(int nAfxDaoError)
  3196. {
  3197.     ASSERT_VALID(this);
  3198.  
  3199.     AfxThrowDaoException(nAfxDaoError);
  3200. }
  3201.  
  3202. #ifdef _DEBUG
  3203. void CDaoQueryDef::AssertValid() const
  3204. {
  3205.     CObject::AssertValid();
  3206. }
  3207.  
  3208. void CDaoQueryDef::Dump(CDumpContext& dc) const
  3209. {
  3210.     ASSERT_VALID(this);
  3211.  
  3212.     CObject::Dump(dc);
  3213.  
  3214.     dc << "m_bOpen = " << m_bOpen;
  3215.     dc << "\nm_bNew = " << m_bNew;
  3216.  
  3217.     dc << "\n";
  3218. }
  3219. #endif //_DEBUG
  3220.  
  3221. //////////////////////////////////////////////////////////////////////////
  3222. // CDaoRecordset
  3223. IMPLEMENT_DYNAMIC(CDaoRecordset, CObject )
  3224.  
  3225. CDaoRecordset::CDaoRecordset(CDaoDatabase* pDatabase)
  3226. {
  3227.     m_bOpen = FALSE;
  3228.  
  3229.     m_pMapFieldCache = NULL;
  3230.     m_pMapFieldIndex = NULL;
  3231.     m_bCheckCacheForDirtyFields = TRUE;
  3232.  
  3233.     m_prgDaoColBindInfo = NULL;
  3234.     m_pulColumnLengths = NULL;
  3235.     m_pbFieldFlags = NULL;
  3236.     m_pbParamFlags = NULL;
  3237.  
  3238.     m_pDAORecordset = NULL;
  3239.     m_pICDAORecordsetGetRows = NULL;
  3240.     m_pQueryDef = NULL;
  3241.     m_pTableDef = NULL;
  3242.     m_pDAOFields = NULL;
  3243.     m_pDAOIndexes = NULL;
  3244.  
  3245.     m_pDatabase = pDatabase;
  3246.  
  3247.     m_nDefaultType = dbOpenDynaset;
  3248.     m_nStatus = 0;
  3249.     m_nFields = 0;
  3250.     m_nParams = 0;
  3251. }
  3252.  
  3253. CDaoRecordset::~CDaoRecordset()
  3254. {
  3255.     if (IsOpen())
  3256.         Close();
  3257.  
  3258.     // Clean up database if necessary
  3259.     if (m_pDatabase != NULL && (m_nStatus & AFX_DAO_IMPLICIT_DB))
  3260.     {
  3261.         m_pDatabase->Close();
  3262.         delete m_pDatabase;
  3263.         m_pDatabase = NULL;
  3264.     }
  3265. }
  3266.  
  3267. void CDaoRecordset::Open(int nOpenType, LPCTSTR lpszSQL, int nOptions)
  3268. {
  3269.     ASSERT_VALID(this);
  3270.     ASSERT(nOpenType == AFX_DAO_USE_DEFAULT_TYPE ||
  3271.         nOpenType == dbOpenDynaset || nOpenType == dbOpenSnapshot ||
  3272.         nOpenType == dbOpenTable);
  3273.  
  3274.     // Re-Opening is invalid.
  3275.     if (IsOpen())
  3276.     {
  3277.         ASSERT(FALSE);
  3278.         return;
  3279.     }
  3280.  
  3281.     if (nOpenType == AFX_DAO_USE_DEFAULT_TYPE)
  3282.         m_nOpenType = m_nDefaultType;
  3283.     else
  3284.         m_nOpenType = nOpenType;
  3285.  
  3286.     // Snapshots readOnly in DAO model.
  3287.     if (m_nOpenType == dbOpenSnapshot)
  3288.         nOptions |= dbReadOnly;
  3289.  
  3290.     // Cache parameters and initialize
  3291.     m_nOptions = nOptions;
  3292.     m_cbFixedLengthFields = 0;
  3293.  
  3294.     // Cache information for use in Requery
  3295.     m_strRequerySQL = lpszSQL;
  3296.     m_strRequeryFilter = m_strFilter;
  3297.     m_strRequerySort = m_strSort;
  3298.  
  3299.     AllocDatabase();
  3300.  
  3301.     m_strSQL = lpszSQL;
  3302.     if (m_strSQL.IsEmpty())
  3303.         m_strSQL = GetDefaultSQL();
  3304.  
  3305.     // Open table directly if option specified
  3306.     if (m_nOpenType == dbOpenTable)
  3307.     {
  3308.         m_pTableDef = new CDaoTableDef(m_pDatabase);
  3309.         m_nStatus |= AFX_DAO_IMPLICIT_TD;
  3310.  
  3311.         TRY
  3312.         {
  3313.             // Must remove the bracket from the name
  3314.             StripBrackets(m_strSQL, m_strSQL.GetBuffer(0));
  3315.             m_strSQL.ReleaseBuffer();
  3316.  
  3317.             m_pTableDef->Open(m_strSQL);
  3318.  
  3319.             // Open the DAO recordset (implicit MoveFirst)
  3320.             DAO_CHECK(m_pTableDef->m_pDAOTableDef->OpenRecordset(
  3321.                 COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
  3322.                 &m_pDAORecordset));
  3323.         }
  3324.         CATCH_ALL(e)
  3325.         {
  3326.             // Once recordset marked as open, Close handles this
  3327.             if (m_pTableDef->IsOpen())
  3328.                 m_pTableDef->Close();
  3329.             delete m_pTableDef;
  3330.             THROW_LAST();
  3331.         }
  3332.         END_CATCH_ALL
  3333.     }
  3334.     else
  3335.     {
  3336.         m_pQueryDef = new CDaoQueryDef(m_pDatabase);
  3337.         m_nStatus |= AFX_DAO_IMPLICIT_QD;
  3338.  
  3339.         TRY
  3340.         {
  3341.             // If initial clause includes potential start of row returning
  3342.             // query, then SQL passed to Open must be valid
  3343.             // (Note: TABLE is valid for UNION-type queries)
  3344.             if ((_tcsnicmp(m_strSQL, _afxSelect2, _countof(_afxSelect2)-1) != 0) &&
  3345.                 (_tcsnicmp(m_strSQL, _afxParameters2, _countof(_afxParameters2)-1) != 0) &&
  3346.                 (_tcsnicmp(m_strSQL, _afxTransform2, _countof(_afxTransform2)-1) != 0) &&
  3347.                 (_tcsnicmp(m_strSQL, _afxTable2, _countof(_afxTable2)-1) != 0))
  3348.             {
  3349.                 BuildSQL();
  3350.             }
  3351.             else
  3352.             {
  3353.                 // Add the filter and sort
  3354.                 if (!m_strFilter.IsEmpty())
  3355.                     m_strSQL += _afxWhere2 + m_strFilter;
  3356.  
  3357.                 if (!m_strSort.IsEmpty())
  3358.                     m_strSQL += _afxOrderBy2 + m_strSort;
  3359.             }
  3360.  
  3361.             // Create and define temp query
  3362.             m_pQueryDef->Open();
  3363.             m_pQueryDef->SetSQL(m_strSQL);
  3364.  
  3365.             BindParameters();
  3366.             // Open the DAO recordset (implicit MoveFirst)
  3367.             DAO_CHECK(m_pQueryDef->m_pDAOQueryDef->_30_OpenRecordset(
  3368.                 COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
  3369.                 &m_pDAORecordset));
  3370.         }
  3371.         CATCH_ALL(e)
  3372.         {
  3373.             // Once recordset marked as open, Close handles this
  3374.             if (m_pQueryDef->IsOpen())
  3375.                 m_pQueryDef->Close();
  3376.             delete m_pQueryDef;
  3377.             THROW_LAST();
  3378.         }
  3379.         END_CATCH_ALL
  3380.     }
  3381.  
  3382.     m_bOpen = TRUE;
  3383.  
  3384.     // Add the recordset to map of Open CDaoRecordsets
  3385.     m_pDatabase->m_mapRecordsets.SetAt(this, this);
  3386.  
  3387.     TRY
  3388.     {
  3389.         BindFields();
  3390.         GetDataAndFixupNulls();
  3391.         SetCursorAttributes();
  3392.     }
  3393.     CATCH_ALL(e)
  3394.     {
  3395.         Close();
  3396.         THROW_LAST();
  3397.     }
  3398.     END_CATCH_ALL
  3399. }
  3400.  
  3401. void CDaoRecordset::Open(CDaoQueryDef* pQueryDef, int nOpenType,
  3402.     int nOptions)
  3403. {
  3404.     ASSERT_VALID(this);
  3405.     // Must pass valid, open QueryDef
  3406.     ASSERT(pQueryDef != NULL);
  3407.     if (!pQueryDef->IsOpen())
  3408.         ThrowDaoException(AFX_DAO_ERROR_OBJECT_NOT_OPEN);
  3409.  
  3410.     // Re-Opening is invalid.
  3411.     if (IsOpen())
  3412.     {
  3413.         ASSERT(FALSE);
  3414.         return;
  3415.     }
  3416.  
  3417.     if (nOpenType == AFX_DAO_USE_DEFAULT_TYPE)
  3418.         m_nOpenType = m_nDefaultType;
  3419.     else
  3420.         m_nOpenType = nOpenType;
  3421.  
  3422.     // Can't open table type recordsets with QueryDef
  3423.     ASSERT(m_nOpenType == dbOpenDynaset || m_nOpenType == dbOpenSnapshot);
  3424.  
  3425.     // Snapshots readOnly in DAO model.
  3426.     if (m_nOpenType == dbOpenSnapshot)
  3427.         nOptions |= dbReadOnly;
  3428.  
  3429.     // Cache parameters and initialize
  3430.     m_nOptions = nOptions;
  3431.     m_cbFixedLengthFields = 0;
  3432.  
  3433.     // Use pre-defined query
  3434.     m_pQueryDef = pQueryDef;
  3435.  
  3436.     // Share the same database object
  3437.     m_pDatabase = m_pQueryDef->m_pDatabase;
  3438.  
  3439.     BindParameters();
  3440.  
  3441.     // Open the DAO recordset (implicit MoveFirst)
  3442.     DAO_CHECK(m_pQueryDef->m_pDAOQueryDef->_30_OpenRecordset(
  3443.         COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
  3444.         &m_pDAORecordset));
  3445.  
  3446.     m_bOpen = TRUE;
  3447.  
  3448.     // Add the recordset to map of Open CDaoRecordsets
  3449.     m_pDatabase->m_mapRecordsets.SetAt(this, this);
  3450.  
  3451.     TRY
  3452.     {
  3453.         BindFields();
  3454.         GetDataAndFixupNulls();
  3455.         SetCursorAttributes();
  3456.     }
  3457.     CATCH_ALL(e)
  3458.     {
  3459.         Close();
  3460.         THROW_LAST();
  3461.     }
  3462.     END_CATCH_ALL
  3463. }
  3464.  
  3465. void CDaoRecordset::Open(CDaoTableDef* pTableDef, int nOpenType,
  3466.     int nOptions)
  3467. {
  3468.     ASSERT_VALID(this);
  3469.     // Must pass valid, open TableDef
  3470.     ASSERT(pTableDef != NULL);
  3471.     if (!pTableDef->IsOpen())
  3472.         ThrowDaoException(AFX_DAO_ERROR_OBJECT_NOT_OPEN);
  3473.     m_pTableDef = pTableDef;
  3474.  
  3475.     // Re-Opening is invalid.
  3476.     if (IsOpen())
  3477.     {
  3478.         ASSERT(FALSE);
  3479.         return;
  3480.     }
  3481.  
  3482.     if (nOpenType == AFX_DAO_USE_DEFAULT_TYPE)
  3483.         m_nOpenType = m_nDefaultType;
  3484.     else
  3485.         m_nOpenType = nOpenType;
  3486.  
  3487.     // Cache parameters and initialize
  3488.     m_nOptions = nOptions;
  3489.     m_cbFixedLengthFields = 0;
  3490.  
  3491.     // Share the same database object
  3492.     m_pDatabase = m_pTableDef->m_pDatabase;
  3493.  
  3494.     // Open the DAO recordset (implicit MoveFirst)
  3495.     DAO_CHECK(m_pTableDef->m_pDAOTableDef->OpenRecordset(
  3496.         COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
  3497.         &m_pDAORecordset));
  3498.  
  3499.     m_bOpen = TRUE;
  3500.  
  3501.     // Add the recordset to map of Open CDaoRecordsets
  3502.     m_pDatabase->m_mapRecordsets.SetAt(this, this);
  3503.  
  3504.     TRY
  3505.     {
  3506.         BindFields();
  3507.         GetDataAndFixupNulls();
  3508.         SetCursorAttributes();
  3509.     }
  3510.     CATCH_ALL(e)
  3511.     {
  3512.         Close();
  3513.         THROW_LAST();
  3514.     }
  3515.     END_CATCH_ALL
  3516. }
  3517.  
  3518. void CDaoRecordset::Close()
  3519. {
  3520.     ASSERT_VALID(this);
  3521.  
  3522.     if (IsOpen())
  3523.         FreeCache();
  3524.  
  3525.     // Clean up name strings in ColBindInfo struct
  3526.     if (m_prgDaoColBindInfo != NULL)
  3527.     {
  3528.         for (int nIndex = 0; nIndex < m_nFields; nIndex++)
  3529.         {
  3530. #ifndef _UNICODE
  3531.             delete[] (LPTSTR)m_prgDaoColBindInfo[nIndex].columnID.lpstr;
  3532.             m_prgDaoColBindInfo[nIndex].columnID.lpstr = NULL;
  3533. #else
  3534.             delete[] (LPTSTR)m_prgDaoColBindInfo[nIndex].columnID.lpwstr;
  3535.             m_prgDaoColBindInfo[nIndex].columnID.lpwstr = NULL;
  3536. #endif
  3537.         }
  3538.     }
  3539.  
  3540.     delete[] m_prgDaoColBindInfo;
  3541.     m_prgDaoColBindInfo = NULL;
  3542.  
  3543.     delete[] m_pulColumnLengths;
  3544.     m_pulColumnLengths = NULL;
  3545.  
  3546.     delete[] m_pbFieldFlags;
  3547.     m_pbFieldFlags = NULL;
  3548.  
  3549.     if (m_pMapFieldIndex != NULL)
  3550.     {
  3551.         delete m_pMapFieldIndex;
  3552.         m_pMapFieldIndex = NULL;
  3553.     }
  3554.  
  3555.     if (m_pDAOIndexes != NULL)
  3556.     {
  3557.         m_pDAOIndexes->Release();
  3558.         m_pDAOIndexes = NULL;
  3559.     }
  3560.  
  3561.     if (m_pDAOFields != NULL)
  3562.     {
  3563.         m_pDAOFields->Release();
  3564.         m_pDAOFields = NULL;
  3565.     }
  3566.  
  3567.     if (m_pICDAORecordsetGetRows != NULL)
  3568.     {
  3569.         m_pICDAORecordsetGetRows->Release();
  3570.         m_pICDAORecordsetGetRows = NULL;
  3571.     }
  3572.  
  3573.     if (m_pDAORecordset != NULL)
  3574.     {
  3575.         DAO_TRACE(m_pDAORecordset->Close());
  3576.         m_pDAORecordset->Release();
  3577.         m_pDAORecordset = NULL;
  3578.     }
  3579.  
  3580.     // Cleanup TableDef if not user supplied
  3581.     if (m_pTableDef != NULL && m_nStatus & AFX_DAO_IMPLICIT_TD)
  3582.     {
  3583.         m_pTableDef->Close();
  3584.         delete m_pTableDef;
  3585.         m_pTableDef = NULL;
  3586.     }
  3587.  
  3588.     // Cleanup QueryDef if not user supplied
  3589.     if (m_pQueryDef != NULL && m_nStatus & AFX_DAO_IMPLICIT_QD)
  3590.     {
  3591.         m_pQueryDef->Close();
  3592.         delete m_pQueryDef;
  3593.         m_pQueryDef = NULL;
  3594.     }
  3595.  
  3596.     m_nStatus &= ~AFX_DAO_IMPLICIT_QD;
  3597.     m_nStatus &= ~AFX_DAO_IMPLICIT_TD;
  3598.     m_pQueryDef = NULL;
  3599.     m_pTableDef = NULL;
  3600.  
  3601.     m_bOpen = FALSE;
  3602.  
  3603.     // Remove the recordset from the CDaoDatabase's map
  3604.     m_pDatabase->m_mapRecordsets.RemoveKey(this);
  3605. }
  3606.  
  3607. void CDaoRecordset::Requery()
  3608. {
  3609.     ASSERT_VALID(this);
  3610.     ASSERT(IsOpen());
  3611.     ASSERT(CanRestart());
  3612.  
  3613.     // If filter or sort strings changed, must Close and Open
  3614.     // This is only effective if m_strFilter/m_strSort used
  3615.     if ((m_pQueryDef != NULL &&
  3616.         (m_nStatus & AFX_DAO_IMPLICIT_QD)) &&
  3617.         ((m_strRequeryFilter != m_strFilter) ||
  3618.         (m_strRequerySort != m_strSort)))
  3619.     {
  3620.         Close();
  3621.         Open(m_nOpenType, m_strRequerySQL, m_nOptions);
  3622.     }
  3623.     else
  3624.     {
  3625.         // Rebind parameters in case values have changed
  3626.         BindParameters();
  3627.  
  3628.         if (m_pQueryDef != NULL)
  3629.         {
  3630.             COleVariant varDisp;
  3631.             varDisp.pdispVal = m_pQueryDef->m_pDAOQueryDef;
  3632.             varDisp.vt = VT_DISPATCH;
  3633.  
  3634.             TRY
  3635.             {
  3636.                 DAO_CHECK(m_pDAORecordset->Requery(varDisp));
  3637.             }
  3638.             CATCH_ALL(e)
  3639.             {
  3640.                 // Reset vt to prevent release of DAOQueryDef
  3641.                 varDisp.vt = VT_EMPTY;
  3642.                 THROW_LAST();
  3643.             }
  3644.             END_CATCH_ALL
  3645.  
  3646.             // Reset vt to prevent release of DAOQueryDef
  3647.             varDisp.vt = VT_EMPTY;
  3648.         }
  3649.         else
  3650.             // Must be a table type recordset (this will fail!)
  3651.             DAO_CHECK(m_pDAORecordset->Requery(_afxOptionalVariant));
  3652.  
  3653.         GetDataAndFixupNulls();
  3654.     }
  3655. }
  3656.  
  3657. CString CDaoRecordset::GetDefaultDBName()
  3658. {
  3659.     ASSERT_VALID(this);
  3660.  
  3661.     // Override and add UNC path to .MDB file
  3662.     return _T("");
  3663. }
  3664.  
  3665. CString CDaoRecordset::GetDefaultSQL()
  3666. {
  3667.     ASSERT_VALID(this);
  3668.  
  3669.     // Override and add table name or entire SQL SELECT statement
  3670.     return _T("");
  3671. }
  3672.  
  3673. void CDaoRecordset::DoFieldExchange(CDaoFieldExchange* /* pFX */)
  3674. {
  3675.     ASSERT_VALID(this);
  3676.  
  3677.     // Do nothing if dynamic binding, otherwise override and add DFX calls
  3678. }
  3679.  
  3680. BOOL CDaoRecordset::IsBOF() const
  3681. {
  3682.     ASSERT_VALID(this);
  3683.     ASSERT(IsOpen());
  3684.  
  3685.     short nBOF;
  3686.     DAO_CHECK(m_pDAORecordset->get_BOF(&nBOF));
  3687.     return nBOF == AFX_DAO_TRUE;
  3688. }
  3689.  
  3690. BOOL CDaoRecordset::IsEOF() const
  3691. {
  3692.     ASSERT_VALID(this);
  3693.     ASSERT(IsOpen());
  3694.  
  3695.     short nEOF;
  3696.     DAO_CHECK(m_pDAORecordset->get_EOF(&nEOF));
  3697.     return nEOF == AFX_DAO_TRUE;
  3698. }
  3699.  
  3700. BOOL CDaoRecordset::IsDeleted() const
  3701. {
  3702.     ASSERT_VALID(this);
  3703.     ASSERT(IsOpen());
  3704.     return m_bDeleted;
  3705. }
  3706.  
  3707. BOOL CDaoRecordset::CanScroll() const
  3708. {
  3709.     ASSERT_VALID(this);
  3710.     ASSERT(IsOpen());
  3711.     return m_bScrollable;
  3712. }
  3713.  
  3714. BOOL CDaoRecordset::CanUpdate() const
  3715. {
  3716.     ASSERT_VALID(this);
  3717.     ASSERT(IsOpen());
  3718.  
  3719.     short nUpdatable;
  3720.     DAO_CHECK(m_pDAORecordset->get_Updatable(&nUpdatable));
  3721.     return nUpdatable == AFX_DAO_TRUE;
  3722. }
  3723.  
  3724. BOOL CDaoRecordset::CanAppend() const
  3725. {
  3726.     ASSERT_VALID(this);
  3727.     ASSERT(IsOpen());
  3728.     return m_bAppendable;
  3729. }
  3730.  
  3731. BOOL CDaoRecordset::CanRestart()
  3732. {
  3733.     ASSERT_VALID(this);
  3734.     ASSERT(IsOpen());
  3735.     ASSERT(m_pDAORecordset != NULL);
  3736.  
  3737.     short nRestartable;
  3738.     DAO_CHECK(m_pDAORecordset->get_Restartable(&nRestartable));
  3739.     return nRestartable == AFX_DAO_TRUE;
  3740. }
  3741.  
  3742. BOOL CDaoRecordset::CanTransact()
  3743. {
  3744.     ASSERT_VALID(this);
  3745.     ASSERT(IsOpen());
  3746.  
  3747.     short nTransactions;
  3748.     DAO_CHECK(m_pDAORecordset->get_Transactions(&nTransactions));
  3749.     return nTransactions == AFX_DAO_TRUE;
  3750. }
  3751.  
  3752. BOOL CDaoRecordset::CanBookmark()
  3753. {
  3754.     ASSERT_VALID(this);
  3755.     ASSERT(IsOpen());
  3756.  
  3757.     short nBookmarkable;
  3758.     DAO_CHECK(m_pDAORecordset->get_Bookmarkable(&nBookmarkable));
  3759.     return nBookmarkable == AFX_DAO_TRUE;
  3760. }
  3761.  
  3762. CString CDaoRecordset::GetName()
  3763. {
  3764.     ASSERT_VALID(this);
  3765.     ASSERT(IsOpen());
  3766.     ASSERT(m_pDAORecordset != NULL);
  3767.  
  3768.     COleVariant var;
  3769.     DAO_CHECK(m_pDAORecordset->get_Name(&V_BSTR(&var)));
  3770.     var.vt = VT_BSTR;
  3771.     return V_BSTRT(&var);
  3772. }
  3773.  
  3774. short CDaoRecordset::GetType()
  3775. {
  3776.     ASSERT_VALID(this);
  3777.     ASSERT(IsOpen());
  3778.     ASSERT(m_pDAORecordset != NULL);
  3779.  
  3780.     short nType;
  3781.     DAO_CHECK(m_pDAORecordset->get_Type(&nType));
  3782.     return nType;
  3783. }
  3784.  
  3785. short CDaoRecordset::GetEditMode()
  3786. {
  3787.     ASSERT_VALID(this);
  3788.     ASSERT(IsOpen());
  3789.     ASSERT(m_pDAORecordset != NULL);
  3790.  
  3791.     short nEditMode;
  3792.     DAO_CHECK(m_pDAORecordset->get_EditMode(&nEditMode));
  3793.     return nEditMode;
  3794. }
  3795.  
  3796. CString CDaoRecordset::GetSQL() const
  3797. {
  3798.     ASSERT_VALID(this);
  3799.     ASSERT(IsOpen());
  3800.     ASSERT(m_pDAORecordset != NULL);
  3801.  
  3802.     return m_strSQL;
  3803. }
  3804.  
  3805. COleDateTime CDaoRecordset::GetDateCreated()
  3806. {
  3807.     ASSERT_VALID(this);
  3808.     ASSERT(IsOpen());
  3809.     ASSERT(m_pDAORecordset != NULL);
  3810.  
  3811.     COleVariant varDate;
  3812.     DAO_CHECK(m_pDAORecordset->get_DateCreated(&varDate));
  3813.     return varDate.date;
  3814. }
  3815.  
  3816. COleDateTime CDaoRecordset::GetDateLastUpdated()
  3817. {
  3818.     ASSERT_VALID(this);
  3819.     ASSERT(IsOpen());
  3820.     ASSERT(m_pDAORecordset != NULL);
  3821.  
  3822.     COleVariant varDate;
  3823.     DAO_CHECK(m_pDAORecordset->get_LastUpdated(&varDate));
  3824.     return varDate.date;
  3825. }
  3826.  
  3827. COleVariant CDaoRecordset::GetLastModifiedBookmark()
  3828. {
  3829.     ASSERT_VALID(this);
  3830.     ASSERT(IsOpen());
  3831.     ASSERT(m_pDAORecordset != NULL);
  3832.  
  3833.     COleVariant var;
  3834.     DAO_CHECK(m_pDAORecordset->get_LastModified(&var.parray));
  3835.     var.vt = VT_ARRAY | VT_UI1;
  3836.  
  3837.     return var;
  3838. }
  3839.  
  3840. CString CDaoRecordset::GetValidationRule()
  3841. {
  3842.     ASSERT_VALID(this);
  3843.     ASSERT(IsOpen());
  3844.     ASSERT(m_pDAORecordset != NULL);
  3845.  
  3846.     COleVariant var;
  3847.     DAO_CHECK(m_pDAORecordset->get_ValidationRule(&V_BSTR(&var)));
  3848.     var.vt = VT_BSTR;
  3849.     return V_BSTRT(&var);
  3850. }
  3851.  
  3852. CString CDaoRecordset::GetValidationText()
  3853. {
  3854.     ASSERT_VALID(this);
  3855.     ASSERT(IsOpen());
  3856.     ASSERT(m_pDAORecordset != NULL);
  3857.  
  3858.     COleVariant var;
  3859.     DAO_CHECK(m_pDAORecordset->get_ValidationText(&V_BSTR(&var)));
  3860.     var.vt = VT_BSTR;
  3861.     return V_BSTRT(&var);
  3862. }
  3863.  
  3864. CString CDaoRecordset::GetCurrentIndex()
  3865. {
  3866.     ASSERT_VALID(this);
  3867.     ASSERT(IsOpen());
  3868.     ASSERT(m_pDAORecordset != NULL);
  3869.  
  3870.     COleVariant var;
  3871.     DAO_CHECK(m_pDAORecordset->get_Index(&V_BSTR(&var)));
  3872.     var.vt = VT_BSTR;
  3873.     return V_BSTRT(&var);
  3874. }
  3875.  
  3876. void CDaoRecordset::SetCurrentIndex(LPCTSTR lpszName)
  3877. {
  3878.     ASSERT_VALID(this);
  3879.     ASSERT(IsOpen());
  3880.     ASSERT(m_pDAORecordset != NULL);
  3881.  
  3882.     COleVariant var(lpszName, VT_BSTRT);
  3883.     DAO_CHECK(m_pDAORecordset->put_Index(V_BSTR(&var)));
  3884.  
  3885.     // Refetch the data
  3886.     GetDataAndFixupNulls();
  3887. }
  3888.  
  3889. long CDaoRecordset::GetRecordCount()
  3890. {
  3891.     ASSERT_VALID(this);
  3892.     ASSERT(IsOpen());
  3893.     ASSERT(m_pDAORecordset != NULL);
  3894.  
  3895.     long lRecordCount;
  3896.     DAO_CHECK(m_pDAORecordset->get_RecordCount(&lRecordCount));
  3897.     return lRecordCount;
  3898. }
  3899.  
  3900. void CDaoRecordset::SetFieldDirty(void* pv, BOOL bDirty)
  3901. {
  3902.     ASSERT_VALID(this);
  3903.  
  3904.     if (m_nFields <= 0)
  3905.     {
  3906.         // Can't set fields dirty if no bound fields
  3907.         ASSERT(FALSE);
  3908.         return;
  3909.     }
  3910.  
  3911.     int nIndex = 0, nIndexEnd;
  3912.  
  3913.     if (pv == NULL)
  3914.         nIndexEnd = m_nFields - 1;
  3915.     else
  3916.     {
  3917.         nIndex = nIndexEnd = GetFieldIndex(pv);
  3918.         ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
  3919.     }
  3920.  
  3921.     while (nIndex <= nIndexEnd)
  3922.     {
  3923.         if (bDirty)
  3924.             SetDirtyFieldStatus(nIndex);
  3925.         else
  3926.             ClearDirtyFieldStatus(nIndex);
  3927.         nIndex++;
  3928.     }
  3929. }
  3930.  
  3931. BOOL CDaoRecordset::IsFieldDirty(void* pv)
  3932. {
  3933.     ASSERT_VALID(this);
  3934.  
  3935.     short nEditMode = GetEditMode();
  3936.  
  3937.     // Fields can't be dirty if not in edit/addnew mode or no fields bound
  3938.     if (nEditMode == dbEditNone || m_nFields <= 0)
  3939.         return FALSE;
  3940.  
  3941.     // Check if cache field values have changed and mark as dirty
  3942.     if (m_bCheckCacheForDirtyFields)
  3943.     {
  3944.         if (nEditMode == dbEditInProgress)
  3945.             MarkForEdit();
  3946.         else
  3947.             MarkForAddNew();
  3948.     }
  3949.  
  3950.     int nIndex = 0, nIndexEnd;
  3951.  
  3952.     if (pv == NULL)
  3953.         nIndexEnd = m_nFields - 1;
  3954.     else
  3955.     {
  3956.         // Get the field index to use status array
  3957.         nIndex = nIndexEnd = GetFieldIndex(pv);
  3958.         ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
  3959.     }
  3960.  
  3961.     BOOL bDirty = FALSE;
  3962.  
  3963.     while (nIndex <= nIndexEnd && !bDirty)
  3964.         bDirty = IsFieldStatusDirty(nIndex++);
  3965.  
  3966.     return bDirty;
  3967. }
  3968.  
  3969. void CDaoRecordset::SetFieldNull(void* pv, BOOL bNull)
  3970. {
  3971.     ASSERT_VALID(this);
  3972.  
  3973.     if (m_nFields <= 0)
  3974.     {
  3975.         ASSERT(FALSE);
  3976.         return;
  3977.     }
  3978.  
  3979.     if (bNull)
  3980.     {
  3981.         // Need field exchange to set value to PSEUDO NULL.
  3982.         CDaoFieldExchange fx(CDaoFieldExchange::SetFieldNull, this, pv);
  3983.         fx.m_nFieldFound = 0;
  3984.         DoFieldExchange(&fx);
  3985.  
  3986.         // If no field found, index will still be zero
  3987.         ASSERT(fx.m_nFieldFound != 0);
  3988.     }
  3989.     else
  3990.     {
  3991.         // Set status array not NULL. Don't need field exchange mechanism.
  3992.         int nIndex = 0, nIndexEnd;
  3993.  
  3994.         if (pv == NULL)
  3995.             nIndexEnd = m_nFields - 1;
  3996.         else
  3997.         {
  3998.             nIndex = nIndexEnd = GetFieldIndex(pv);
  3999.             ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
  4000.         }
  4001.  
  4002.         while (nIndex <= nIndexEnd)
  4003.         {
  4004.             ClearNullFieldStatus(nIndex);
  4005.             nIndex++;
  4006.         }
  4007.     }
  4008. }
  4009.  
  4010. BOOL CDaoRecordset::IsFieldNull(void* pv)
  4011. {
  4012.     ASSERT_VALID(this);
  4013.  
  4014.     if (m_nFields <= 0)
  4015.     {
  4016.         ASSERT(FALSE);
  4017.         return FALSE;
  4018.     }
  4019.  
  4020.     int nIndex = 0, nIndexEnd;
  4021.  
  4022.     if (pv == NULL)
  4023.         nIndexEnd = m_nFields - 1;
  4024.     else
  4025.     {
  4026.         // Get the field index to use status array
  4027.         nIndex = nIndexEnd = GetFieldIndex(pv);
  4028.         ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
  4029.     }
  4030.  
  4031.     BOOL bNull = FALSE;
  4032.  
  4033.     while (nIndex <= nIndexEnd && !bNull)
  4034.         bNull = IsFieldStatusNull(nIndex++);
  4035.  
  4036.     return bNull;
  4037. }
  4038.  
  4039. BOOL CDaoRecordset::IsFieldNullable(void* pv)
  4040. {
  4041.     ASSERT_VALID(this);
  4042.  
  4043.     if (m_nFields <= 0)
  4044.     {
  4045.         ASSERT(FALSE);
  4046.         return FALSE;
  4047.     }
  4048.  
  4049.     int nIndex = 0, nIndexEnd;
  4050.  
  4051.     if (pv == NULL)
  4052.         nIndexEnd = m_nFields - 1;
  4053.     else
  4054.     {
  4055.         // Get the field index to use status array
  4056.         nIndex = nIndexEnd = GetFieldIndex(pv);
  4057.         ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
  4058.     }
  4059.  
  4060.     BOOL bNullable = FALSE;
  4061.  
  4062.     while (nIndex <= nIndexEnd && !bNullable)
  4063.     {
  4064.         if (!IsFieldStatusNullableKnown(nIndex))
  4065.         {
  4066.             CDaoFieldInfo fieldinfo;
  4067.             GetFieldInfo(nIndex, fieldinfo, AFX_DAO_SECONDARY_INFO);
  4068.             bNullable = !fieldinfo.m_bRequired;
  4069.             if (bNullable)
  4070.                 SetNullableFieldStatus(nIndex);
  4071.             SetNullableKnownFieldStatus(nIndex);
  4072.         }
  4073.         else
  4074.             bNullable = IsFieldStatusNullable(nIndex);
  4075.  
  4076.         nIndex++;
  4077.     }
  4078.  
  4079.     return bNullable;
  4080. }
  4081.  
  4082. short CDaoRecordset::GetFieldCount()
  4083. {
  4084.     ASSERT_VALID(this);
  4085.  
  4086.     short nFields;
  4087.  
  4088.     if (m_pDAOFields == NULL)
  4089.         InitFieldsCollection();
  4090.  
  4091.     DAO_CHECK(m_pDAOFields->get_Count(&nFields));
  4092.     return nFields;
  4093. }
  4094.  
  4095. void CDaoRecordset::GetFieldInfo(int nIndex, CDaoFieldInfo& fieldinfo,
  4096.     DWORD dwInfoOptions)
  4097. {
  4098.     ASSERT_VALID(this);
  4099.  
  4100.     if (m_pDAOFields == NULL)
  4101.         InitFieldsCollection();
  4102.  
  4103.     // Get DAOField object and fill in field info struct
  4104.     DAOField* pDAOField;
  4105.     DAO_CHECK(m_pDAOFields->get_Item(
  4106.         COleVariant((long)nIndex), &pDAOField));
  4107.     AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
  4108.  
  4109.     // Clean up
  4110.     pDAOField->Release();
  4111. }
  4112.  
  4113. void CDaoRecordset::GetFieldInfo(LPCTSTR lpszName,
  4114.     CDaoFieldInfo& fieldinfo, DWORD dwInfoOptions)
  4115. {
  4116.     ASSERT_VALID(this);
  4117.  
  4118.     if (m_pDAOFields == NULL)
  4119.         InitFieldsCollection();
  4120.  
  4121.     // Get DAOField object and fill in field info struct
  4122.     DAOField* pDAOField;
  4123.     DAO_CHECK(m_pDAOFields->get_Item(
  4124.         COleVariant(lpszName, VT_BSTRT), &pDAOField));
  4125.     AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
  4126.  
  4127.     // Clean up
  4128.     pDAOField->Release();
  4129. }
  4130.  
  4131. short CDaoRecordset::GetIndexCount()
  4132. {
  4133.     ASSERT_VALID(this);
  4134.  
  4135.     short nIndexes;
  4136.  
  4137.     if (m_pDAOIndexes == NULL)
  4138.         InitIndexesCollection();
  4139.  
  4140.     DAO_CHECK(m_pDAOIndexes->get_Count(&nIndexes));
  4141.     return nIndexes;
  4142. }
  4143.  
  4144. void CDaoRecordset::GetIndexInfo(int nIndex, CDaoIndexInfo& indexinfo,
  4145.     DWORD dwInfoOptions)
  4146. {
  4147.     ASSERT_VALID(this);
  4148.  
  4149.     if (m_pDAOIndexes == NULL)
  4150.         InitIndexesCollection();
  4151.  
  4152.     // Get DAOField object and fill in field info struct
  4153.     DAOIndex* pDAOIndex;
  4154.     DAO_CHECK(m_pDAOIndexes->get_Item(
  4155.         COleVariant((long)nIndex), &pDAOIndex));
  4156.     AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
  4157.  
  4158.     // Clean up
  4159.     pDAOIndex->Release();
  4160. }
  4161.  
  4162. void CDaoRecordset::GetIndexInfo(LPCTSTR lpszName,
  4163.     CDaoIndexInfo& indexinfo, DWORD dwInfoOptions)
  4164. {
  4165.     ASSERT_VALID(this);
  4166.  
  4167.     if (m_pDAOIndexes == NULL)
  4168.         InitIndexesCollection();
  4169.  
  4170.     // Get DAOField object and fill in field info struct
  4171.     DAOIndex* pDAOIndex;
  4172.     DAO_CHECK(m_pDAOIndexes->get_Item(
  4173.         COleVariant(lpszName, VT_BSTRT), &pDAOIndex));
  4174.     AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
  4175.  
  4176.     // Clean up
  4177.     pDAOIndex->Release();
  4178. }
  4179.  
  4180. COleVariant CDaoRecordset::GetBookmark()
  4181. {
  4182.     ASSERT_VALID(this);
  4183.     ASSERT(IsOpen());
  4184.     ASSERT(m_pDAORecordset != NULL);
  4185.  
  4186.     COleVariant var;
  4187.     DAO_CHECK(m_pDAORecordset->get_Bookmark(&var.parray));
  4188.     var.vt = VT_ARRAY | VT_UI1;
  4189.  
  4190.     return var;
  4191. }
  4192.  
  4193. void CDaoRecordset::SetBookmark(COleVariant varBookmark)
  4194. {
  4195.     ASSERT_VALID(this);
  4196.     ASSERT(IsOpen());
  4197.     ASSERT(m_pDAORecordset != NULL);
  4198.  
  4199.     DAO_CHECK(m_pDAORecordset->put_Bookmark(&varBookmark.parray));
  4200.  
  4201.     GetDataAndFixupNulls();
  4202. }
  4203.  
  4204. long CDaoRecordset::GetAbsolutePosition()
  4205. {
  4206.     ASSERT_VALID(this);
  4207.     ASSERT(IsOpen());
  4208.     ASSERT(m_pDAORecordset != NULL);
  4209.  
  4210.     long lPosition;
  4211.     DAO_CHECK(m_pDAORecordset->get_AbsolutePosition(&lPosition));
  4212.     return lPosition;
  4213. }
  4214.  
  4215. void CDaoRecordset::SetAbsolutePosition(long lPosition)
  4216. {
  4217.     ASSERT_VALID(this);
  4218.     ASSERT(IsOpen());
  4219.     ASSERT(m_pDAORecordset != NULL);
  4220.  
  4221.     DAO_CHECK(m_pDAORecordset->put_AbsolutePosition(lPosition));
  4222.  
  4223.     GetDataAndFixupNulls();
  4224. }
  4225.  
  4226. float CDaoRecordset::GetPercentPosition()
  4227. {
  4228.     ASSERT_VALID(this);
  4229.     ASSERT(IsOpen());
  4230.     ASSERT(m_pDAORecordset != NULL);
  4231.  
  4232.     float fPosition;
  4233.     DAO_CHECK(m_pDAORecordset->get_PercentPosition(&fPosition));
  4234.     return fPosition;
  4235. }
  4236.  
  4237. void CDaoRecordset::SetPercentPosition(float fPosition)
  4238. {
  4239.     ASSERT_VALID(this);
  4240.     ASSERT(IsOpen());
  4241.     ASSERT(m_pDAORecordset != NULL);
  4242.  
  4243.     DAO_CHECK(m_pDAORecordset->put_PercentPosition(fPosition));
  4244.  
  4245.     GetDataAndFixupNulls();
  4246. }
  4247.  
  4248. void CDaoRecordset::MoveNext()
  4249. {
  4250.     ASSERT_VALID(this);
  4251.  
  4252.     Move(AFX_DAO_NEXT);
  4253. }
  4254.  
  4255. void CDaoRecordset::MovePrev()
  4256. {
  4257.     ASSERT_VALID(this);
  4258.  
  4259.     Move(AFX_DAO_PREV);
  4260. }
  4261.  
  4262. void CDaoRecordset::MoveFirst()
  4263. {
  4264.     ASSERT_VALID(this);
  4265.  
  4266.     Move(AFX_DAO_FIRST);
  4267. }
  4268.  
  4269. void CDaoRecordset::MoveLast()
  4270. {
  4271.     ASSERT_VALID(this);
  4272.  
  4273.     Move(AFX_DAO_LAST);
  4274. }
  4275.  
  4276. void CDaoRecordset::Move(long lRows)
  4277. {
  4278.     ASSERT_VALID(this);
  4279.     ASSERT(IsOpen());
  4280.     ASSERT(m_pDAORecordset != NULL);
  4281.  
  4282.     switch(lRows)
  4283.     {
  4284.     case AFX_DAO_NEXT:
  4285.         DAO_CHECK(m_pDAORecordset->MoveNext());
  4286.         break;
  4287.  
  4288.     case AFX_DAO_PREV:
  4289.         DAO_CHECK(m_pDAORecordset->MovePrevious());
  4290.         break;
  4291.  
  4292.     case AFX_DAO_FIRST:
  4293.         DAO_CHECK(m_pDAORecordset->MoveFirst());
  4294.         break;
  4295.  
  4296.     case AFX_DAO_LAST:
  4297.         DAO_CHECK(m_pDAORecordset->_30_MoveLast());
  4298.         break;
  4299.  
  4300.     // General case
  4301.     default:
  4302.         // Call Move without getting Bookmark (using unitialized variant).
  4303.         DAO_CHECK(m_pDAORecordset->Move(lRows, COleVariant()));
  4304.  
  4305.     }
  4306.  
  4307.     GetDataAndFixupNulls();
  4308. }
  4309.  
  4310. BOOL CDaoRecordset::FindNext(LPCTSTR lpszFilter)
  4311. {
  4312.     ASSERT_VALID(this);
  4313.  
  4314.     return Find(AFX_DAO_NEXT, lpszFilter);
  4315. }
  4316.  
  4317. BOOL CDaoRecordset::FindPrev(LPCTSTR lpszFilter)
  4318. {
  4319.     ASSERT_VALID(this);
  4320.  
  4321.     return Find(AFX_DAO_PREV, lpszFilter);
  4322. }
  4323.  
  4324. BOOL CDaoRecordset::FindFirst(LPCTSTR lpszFilter)
  4325. {
  4326.     ASSERT_VALID(this);
  4327.  
  4328.     return Find(AFX_DAO_FIRST, lpszFilter);
  4329. }
  4330.  
  4331. BOOL CDaoRecordset::FindLast(LPCTSTR lpszFilter)
  4332. {
  4333.     ASSERT_VALID(this);
  4334.  
  4335.     return Find(AFX_DAO_LAST, lpszFilter);
  4336. }
  4337.  
  4338. BOOL CDaoRecordset::Find(long lType, LPCTSTR lpszFilter)
  4339. {
  4340.     ASSERT_VALID(this);
  4341.     ASSERT(IsOpen());
  4342.     ASSERT(m_pDAORecordset != NULL);
  4343.  
  4344.     COleVariant var(lpszFilter, VT_BSTRT);
  4345.  
  4346.     switch(lType)
  4347.     {
  4348.     default:
  4349.         // Invalid Find type!
  4350.         ASSERT(FALSE);
  4351.  
  4352.         // fall through to FindNext case
  4353.  
  4354.     case AFX_DAO_NEXT:
  4355.         DAO_CHECK(m_pDAORecordset->FindNext(V_BSTR(&var)));
  4356.         break;
  4357.  
  4358.     case AFX_DAO_PREV:
  4359.         DAO_CHECK(m_pDAORecordset->FindPrevious(V_BSTR(&var)));
  4360.         break;
  4361.  
  4362.     case AFX_DAO_FIRST:
  4363.         DAO_CHECK(m_pDAORecordset->FindFirst(V_BSTR(&var)));
  4364.         break;
  4365.  
  4366.     case AFX_DAO_LAST:
  4367.         DAO_CHECK(m_pDAORecordset->FindLast(V_BSTR(&var)));
  4368.         break;
  4369.     }
  4370.  
  4371.     BOOL bMatch = IsMatch();
  4372.     if (bMatch)
  4373.         GetDataAndFixupNulls();
  4374.  
  4375.     return bMatch;
  4376. }
  4377.  
  4378. BOOL CDaoRecordset::Seek(LPCTSTR lpszComparison, COleVariant* pKey1,
  4379.     COleVariant* pKey2, COleVariant* pKey3)
  4380. {
  4381.     ASSERT_VALID(this);
  4382.     ASSERT(IsOpen());
  4383.     ASSERT(m_pDAORecordset != NULL);
  4384.     ASSERT(m_nOpenType == dbOpenTable);
  4385.  
  4386.     // Must have at least one key
  4387.     ASSERT(pKey1 != NULL);
  4388.  
  4389.     COleVariant varComparison(lpszComparison, VT_BSTRT);
  4390.  
  4391.     DAO_CHECK(m_pDAORecordset->Seek(V_BSTR(&varComparison),
  4392.         pKey1 != NULL ? (VARIANT)*pKey1 : _afxOptionalVariant,
  4393.         pKey2 != NULL ? (VARIANT)*pKey2 : _afxOptionalVariant,
  4394.         pKey3 != NULL ? (VARIANT)*pKey3 : _afxOptionalVariant,
  4395.         _afxOptionalVariant, _afxOptionalVariant, _afxOptionalVariant,
  4396.         _afxOptionalVariant, _afxOptionalVariant, _afxOptionalVariant,
  4397.         _afxOptionalVariant, _afxOptionalVariant, _afxOptionalVariant,
  4398.         _afxOptionalVariant));
  4399.  
  4400.     BOOL bMatch = IsMatch();
  4401.     if (bMatch)
  4402.         GetDataAndFixupNulls();
  4403.  
  4404.     return bMatch;
  4405. }
  4406.  
  4407. BOOL CDaoRecordset::Seek(LPCTSTR lpszComparison, COleVariant* pKeyArray,
  4408.     WORD nKeys)
  4409. {
  4410.     ASSERT_VALID(this);
  4411.     ASSERT(IsOpen());
  4412.     ASSERT(m_pDAORecordset != NULL);
  4413.     ASSERT(m_nOpenType == dbOpenTable);
  4414.  
  4415.     // Must have at least one key and no more than 13
  4416.     ASSERT(nKeys > 0);
  4417.     ASSERT(nKeys < 14);
  4418.  
  4419.     COleVariant varComparison(lpszComparison, VT_BSTRT);
  4420.     LPVARIANT pVarArray[13];
  4421.  
  4422.     for (WORD nIndex = 0; nIndex < nKeys; nIndex++)
  4423.         pVarArray[nIndex] = &pKeyArray[nIndex];
  4424.  
  4425.     for (;nIndex < 13; nIndex++)
  4426.         pVarArray[nIndex] = &_afxOptionalVariant;
  4427.  
  4428.     DAO_CHECK(m_pDAORecordset->Seek(V_BSTR(&varComparison),
  4429.         *pVarArray[0], *pVarArray[1], *pVarArray[2], *pVarArray[3],
  4430.         *pVarArray[4], *pVarArray[5], *pVarArray[6], *pVarArray[7],
  4431.         *pVarArray[8], *pVarArray[9], *pVarArray[10], *pVarArray[11],
  4432.         *pVarArray[12]));
  4433.  
  4434.     BOOL bMatch = IsMatch();
  4435.     if (bMatch)
  4436.         GetDataAndFixupNulls();
  4437.  
  4438.     return bMatch;
  4439. }
  4440.  
  4441. void CDaoRecordset::CancelUpdate()
  4442. {
  4443.     ASSERT_VALID(this);
  4444.     ASSERT(IsOpen());
  4445.     ASSERT(m_pDAORecordset != NULL);
  4446.  
  4447.     DAO_CHECK(m_pDAORecordset->_30_CancelUpdate());
  4448.  
  4449.     // Restore cache if necessary
  4450.     if (m_bCheckCacheForDirtyFields && m_nFields > 0)
  4451.         LoadFields();
  4452. }
  4453.  
  4454. void CDaoRecordset::SetLockingMode(BOOL bPessimistic)
  4455. {
  4456.     ASSERT_VALID(this);
  4457.     ASSERT(IsOpen());
  4458.     ASSERT(m_pDAORecordset != NULL);
  4459.  
  4460.     DAO_CHECK(m_pDAORecordset->put_LockEdits(
  4461.         (short)(bPessimistic ? AFX_DAO_TRUE : AFX_DAO_FALSE)));
  4462. }
  4463.  
  4464. BOOL CDaoRecordset::GetLockingMode()
  4465. {
  4466.     ASSERT_VALID(this);
  4467.     ASSERT(IsOpen());
  4468.     ASSERT(m_pDAORecordset != NULL);
  4469.  
  4470.     short nLockEdits;
  4471.     DAO_CHECK(m_pDAORecordset->get_LockEdits(&nLockEdits));
  4472.     return nLockEdits == AFX_DAO_TRUE;
  4473. }
  4474.  
  4475. void CDaoRecordset::SetCacheStart(COleVariant varBookmark)
  4476. {
  4477.     ASSERT_VALID(this);
  4478.     ASSERT(IsOpen());
  4479.     ASSERT(m_pDAORecordset != NULL);
  4480.  
  4481.     DAO_CHECK(m_pDAORecordset->put_CacheStart(&varBookmark.parray));
  4482. }
  4483.  
  4484. COleVariant CDaoRecordset::GetCacheStart()
  4485. {
  4486.     ASSERT_VALID(this);
  4487.     ASSERT(IsOpen());
  4488.     ASSERT(m_pDAORecordset != NULL);
  4489.  
  4490.     COleVariant var;
  4491.     DAO_CHECK(m_pDAORecordset->get_CacheStart(&var.parray));
  4492.     var.vt = VT_ARRAY | VT_UI1;
  4493.  
  4494.     return var;
  4495. }
  4496.  
  4497. void CDaoRecordset::SetCacheSize(long lSize)
  4498. {
  4499.     ASSERT_VALID(this);
  4500.     ASSERT(IsOpen());
  4501.     ASSERT(m_pDAORecordset != NULL);
  4502.  
  4503.     DAO_CHECK(m_pDAORecordset->put_CacheSize(lSize));
  4504. }
  4505.  
  4506. long CDaoRecordset::GetCacheSize()
  4507. {
  4508.     ASSERT_VALID(this);
  4509.     ASSERT(IsOpen());
  4510.     ASSERT(m_pDAORecordset != NULL);
  4511.  
  4512.     long lSize;
  4513.     DAO_CHECK(m_pDAORecordset->get_CacheSize(&lSize));
  4514.     return lSize;
  4515. }
  4516.  
  4517. void CDaoRecordset::FillCache(long* pSize, COleVariant* pBookmark)
  4518. {
  4519.     ASSERT_VALID(this);
  4520.     ASSERT(IsOpen());
  4521.     ASSERT(m_pDAORecordset != NULL);
  4522.  
  4523.     DAO_CHECK(m_pDAORecordset->FillCache(
  4524.         pSize != NULL ? (VARIANT)COleVariant(*pSize) : _afxOptionalVariant,
  4525.         pBookmark != NULL ? (VARIANT)*pBookmark : _afxOptionalVariant));
  4526. }
  4527.  
  4528. void CDaoRecordset::AddNew()
  4529. {
  4530.     ASSERT_VALID(this);
  4531.     ASSERT(IsOpen());
  4532.     ASSERT(m_pDAORecordset != NULL);
  4533.  
  4534.     if (m_bCheckCacheForDirtyFields && m_nFields > 0)
  4535.     {
  4536.         short nEditMode = GetEditMode();
  4537.         if (nEditMode != dbEditAdd)
  4538.         {
  4539.             // Store fields if necessary (fields already stored if edit mode)
  4540.             if (nEditMode != dbEditInProgress)
  4541.             {
  4542.                 AllocCache();
  4543.                 StoreFields();
  4544.             }
  4545.  
  4546.             // Set all fields NULL and not dirty
  4547.             SetFieldNull(NULL);
  4548.             SetFieldDirty(NULL, FALSE);
  4549.         }
  4550.     }
  4551.  
  4552.     DAO_CHECK(m_pDAORecordset->AddNew());
  4553. }
  4554.  
  4555. void CDaoRecordset::Edit()
  4556. {
  4557.     ASSERT_VALID(this);
  4558.     ASSERT(IsOpen());
  4559.     ASSERT(m_pDAORecordset != NULL);
  4560.  
  4561.     if (m_bCheckCacheForDirtyFields && m_nFields > 0)
  4562.     {
  4563.         short nEditMode = GetEditMode();
  4564.         if (nEditMode != dbEditInProgress)
  4565.         {
  4566.             if (nEditMode == dbEditNone)
  4567.             {
  4568.                 // Save fields for restore/dirty checking later
  4569.                 AllocCache();
  4570.                 StoreFields();
  4571.                 SetFieldDirty(NULL, FALSE);
  4572.             }
  4573.             else
  4574.                 // Load in fields cached on AddNew call prior to Edit
  4575.                 LoadFields();
  4576.         }
  4577.     }
  4578.  
  4579.     DAO_CHECK(m_pDAORecordset->Edit());
  4580. }
  4581.  
  4582. void CDaoRecordset::Update()
  4583. {
  4584.     ASSERT_VALID(this);
  4585.     ASSERT(IsOpen());
  4586.     ASSERT(m_pDAORecordset != NULL);
  4587.  
  4588.     int nMode = 0;
  4589.  
  4590.     // If caching, compare cache to current values and save state
  4591.     if (m_nFields > 0)
  4592.     {
  4593.         if (m_bCheckCacheForDirtyFields)
  4594.         {
  4595.             IsFieldDirty(NULL);
  4596.             nMode = GetEditMode();
  4597.         }
  4598.  
  4599.         // Set all field values of all fields marked dirty
  4600.         SetDirtyFields();
  4601.     }
  4602.  
  4603.     DAO_CHECK(m_pDAORecordset->_30_Update());
  4604.  
  4605.     // Restore data if data cached and were in add mode
  4606.     if (m_bCheckCacheForDirtyFields && m_nFields > 0 &&
  4607.         nMode == dbEditAdd)
  4608.     {
  4609.         LoadFields();
  4610.     }
  4611. }
  4612.  
  4613. void CDaoRecordset::Delete()
  4614. {
  4615.     ASSERT_VALID(this);
  4616.     ASSERT(IsOpen());
  4617.     ASSERT(m_pDAORecordset != NULL);
  4618.  
  4619.     DAO_CHECK(m_pDAORecordset->Delete());
  4620.  
  4621.     if (m_bCheckCacheForDirtyFields && m_nFields > 0)
  4622.     {
  4623.         SetFieldNull(NULL);
  4624.         SetFieldDirty(NULL, FALSE);
  4625.     }
  4626.  
  4627.     m_bDeleted = TRUE;
  4628. }
  4629.  
  4630. COleVariant CDaoRecordset::GetFieldValue(LPCTSTR lpszName)
  4631. {
  4632.     COleVariant var;
  4633.     GetFieldValue(lpszName, var);
  4634.     return var;
  4635. }
  4636.  
  4637. COleVariant CDaoRecordset::GetFieldValue(int nIndex)
  4638. {
  4639.     COleVariant var;
  4640.     GetFieldValue(nIndex, var);
  4641.     return var;
  4642. }
  4643.  
  4644. void CDaoRecordset::GetFieldValue(LPCTSTR lpszName, COleVariant& varValue)
  4645. {
  4646.     ASSERT_VALID(this);
  4647.     ASSERT(IsOpen());
  4648.     ASSERT(m_pDAORecordset != NULL);
  4649.  
  4650.     // Clear out variant
  4651.     varValue.Clear();
  4652.  
  4653.     // Use DAO optimization. get_Collect will get the field object from
  4654.     // the fields collection and fetch the value
  4655.     DAO_CHECK(m_pDAORecordset->get_Collect(
  4656.         COleVariant(lpszName, VT_BSTRT), &varValue));
  4657. }
  4658.  
  4659. void CDaoRecordset::GetFieldValue(int nIndex, COleVariant& varValue)
  4660. {
  4661.     ASSERT_VALID(this);
  4662.     ASSERT(IsOpen());
  4663.     ASSERT(m_pDAORecordset != NULL);
  4664.  
  4665.     // Clear out variant
  4666.     varValue.Clear();
  4667.  
  4668.     // Use DAO optimization. get_Collect will get the field object from
  4669.     // the fields collection and fetch the value
  4670.     DAO_CHECK(m_pDAORecordset->get_Collect(
  4671.         COleVariant((long)nIndex), &varValue));
  4672. }
  4673.  
  4674. void CDaoRecordset::SetFieldValue(LPCTSTR lpszName,
  4675.     const COleVariant& varValue)
  4676. {
  4677.     ASSERT_VALID(this);
  4678.     ASSERT(IsOpen());
  4679.     ASSERT(m_pDAORecordset != NULL);
  4680.  
  4681.     // Use DAO optimization. get_Collect will get the field object from
  4682.     // the fields collection and fetch the value
  4683.     DAO_CHECK(m_pDAORecordset->put_Collect(
  4684.         COleVariant(lpszName, VT_BSTRT), varValue));
  4685. }
  4686.  
  4687. void CDaoRecordset::SetFieldValue(int nIndex,
  4688.     const COleVariant& varValue)
  4689. {
  4690.     ASSERT_VALID(this);
  4691.     ASSERT(IsOpen());
  4692.     ASSERT(m_pDAORecordset != NULL);
  4693.  
  4694.     // Use DAO optimization. put_Collect will get the field object from
  4695.     // the fields collection and write the value
  4696.     DAO_CHECK(m_pDAORecordset->put_Collect(
  4697.         COleVariant((long)nIndex), varValue));
  4698. }
  4699.  
  4700. void CDaoRecordset::SetFieldValue(int nIndex,
  4701.     LPCTSTR lpszValue)
  4702. {
  4703.     COleVariant varValue(lpszValue, VT_BSTRT);
  4704.     SetFieldValue(nIndex, varValue);
  4705. }
  4706.  
  4707. void CDaoRecordset::SetFieldValue(LPCTSTR lpszName,
  4708.     LPCTSTR lpszValue)
  4709. {
  4710.     COleVariant varValue(lpszValue, VT_BSTRT);
  4711.     SetFieldValue(lpszName, varValue);
  4712. }
  4713.  
  4714. void CDaoRecordset::SetFieldValueNull(LPCTSTR lpszName)
  4715. {
  4716.     ASSERT_VALID(this);
  4717.  
  4718.     SetFieldValue(lpszName, _afxNullVariant);
  4719. }
  4720.  
  4721. void CDaoRecordset::SetFieldValueNull(int nIndex)
  4722. {
  4723.     ASSERT_VALID(this);
  4724.  
  4725.     SetFieldValue(nIndex, _afxNullVariant);
  4726. }
  4727.  
  4728. COleVariant CDaoRecordset::GetParamValue(LPCTSTR lpszName)
  4729. {
  4730.     ASSERT_VALID(this);
  4731.     ASSERT(IsOpen());
  4732.     ASSERT(m_pQueryDef != NULL);
  4733.  
  4734.     return m_pQueryDef->GetParamValue(lpszName);
  4735. }
  4736.  
  4737. COleVariant CDaoRecordset::GetParamValue(int nIndex)
  4738. {
  4739.     ASSERT_VALID(this);
  4740.     ASSERT(IsOpen());
  4741.     ASSERT(m_pQueryDef != NULL);
  4742.  
  4743.     return m_pQueryDef->GetParamValue(nIndex);
  4744. }
  4745.  
  4746. void CDaoRecordset::SetParamValue(LPCTSTR lpszName,
  4747.     const COleVariant& varValue)
  4748. {
  4749.     ASSERT_VALID(this);
  4750.     ASSERT(IsOpen());
  4751.     ASSERT(m_pQueryDef != NULL);
  4752.  
  4753.     m_pQueryDef->SetParamValue(lpszName, varValue);
  4754. }
  4755.  
  4756. void CDaoRecordset::SetParamValue(int nIndex,
  4757.     const COleVariant& varValue)
  4758. {
  4759.     ASSERT_VALID(this);
  4760.     ASSERT(IsOpen());
  4761.     ASSERT(m_pQueryDef != NULL);
  4762.  
  4763.     m_pQueryDef->SetParamValue(nIndex, varValue);
  4764. }
  4765.  
  4766. void CDaoRecordset::SetParamValueNull(LPCTSTR lpszName)
  4767. {
  4768.     ASSERT_VALID(this);
  4769.  
  4770.     SetParamValue(lpszName, _afxNullVariant);
  4771. }
  4772.  
  4773. void CDaoRecordset::SetParamValueNull(int nIndex)
  4774. {
  4775.     ASSERT_VALID(this);
  4776.  
  4777.     SetParamValue(nIndex, _afxNullVariant);
  4778. }
  4779.  
  4780. //Implementation functions
  4781. DWORD CDaoRecordset::GetFieldLength(int nFieldIndex)
  4782. {
  4783.     ASSERT_VALID(this);
  4784.     ASSERT(IsOpen());
  4785.  
  4786.     return m_pulColumnLengths[nFieldIndex];
  4787. }
  4788.  
  4789. void CDaoRecordset::InitFieldsCollection()
  4790. {
  4791.     ASSERT_VALID(this);
  4792.     ASSERT(IsOpen());
  4793.  
  4794.     DAO_CHECK(m_pDAORecordset->get_Fields(&m_pDAOFields));
  4795. }
  4796.  
  4797. void CDaoRecordset::InitIndexesCollection()
  4798. {
  4799.     ASSERT_VALID(this);
  4800.     ASSERT(IsOpen());
  4801.  
  4802.     DAO_CHECK(m_pTableDef->m_pDAOTableDef->get_Indexes(&m_pDAOIndexes));
  4803. }
  4804.  
  4805. // "PARAMETERS <parameter list>;"
  4806. // "SELECT <select list> FROM <table list>"
  4807. // " WHERE <m_strFilter> ORDER BY <m_strSort>"
  4808. void CDaoRecordset::BuildSQL()
  4809. {
  4810.     ASSERT_VALID(this);
  4811.  
  4812.     // Assumes m_strSQL represents table list
  4813.     CString strTableName = m_strSQL;
  4814.     m_strSQL.Empty();
  4815.  
  4816.     if (m_nParams > 0)
  4817.         BuildParameterList();
  4818.     BuildSelectList();
  4819.     m_strSQL += _afxFrom2 + strTableName;
  4820.  
  4821.     if (!m_strFilter.IsEmpty())
  4822.     {
  4823.         m_strSQL += _afxWhere2;
  4824.         m_strSQL += m_strFilter;
  4825.     }
  4826.  
  4827.     if (!m_strSort.IsEmpty())
  4828.     {
  4829.         m_strSQL += _afxOrderBy2;
  4830.         m_strSQL += m_strSort;
  4831.     }
  4832. }
  4833.  
  4834. void CDaoRecordset::AllocDatabase()
  4835. {
  4836.     ASSERT_VALID(this);
  4837.  
  4838.     // Allocate and maintain database if necessary
  4839.     if (m_pDatabase == NULL)
  4840.     {
  4841.         m_pDatabase = new CDaoDatabase;
  4842.         m_pDatabase->m_nStatus |= AFX_DAO_IMPLICIT_DB;
  4843.         m_nStatus |= AFX_DAO_IMPLICIT_DB;
  4844.     }
  4845.  
  4846.     // Open Database if necessary
  4847.     if (!m_pDatabase->IsOpen())
  4848.         m_pDatabase->Open((LPCTSTR)GetDefaultDBName(), FALSE, FALSE, NULL);
  4849. }
  4850.  
  4851. void CDaoRecordset::BuildSelectList()
  4852. {
  4853.     ASSERT_VALID(this);
  4854.     ASSERT(m_nFields > 0);
  4855.  
  4856.     m_strSQL += _afxSelect2;
  4857.  
  4858.     CDaoFieldExchange fx(CDaoFieldExchange::AddToSelectList, this);
  4859.     DoFieldExchange(&fx);
  4860. }
  4861.  
  4862. void CDaoRecordset::BuildParameterList()
  4863. {
  4864.     ASSERT_VALID(this);
  4865.     ASSERT(m_nParams > 0);
  4866.  
  4867.     m_strSQL += _afxParameters2;
  4868.  
  4869.     CDaoFieldExchange fx(CDaoFieldExchange::AddToParameterList, this);
  4870.     DoFieldExchange(&fx);
  4871.  
  4872.     if (fx.m_nParam != 0)
  4873.         m_strSQL += _T(";");
  4874.     else
  4875.         m_strSQL.Empty();
  4876. }
  4877.  
  4878. void CDaoRecordset::BindFields()
  4879. {
  4880.     ASSERT_VALID(this);
  4881.  
  4882.     if (m_nFields > 0)
  4883.     {
  4884.         // Setup the DAO binding struct
  4885.         ASSERT(m_prgDaoColBindInfo == NULL);
  4886.         m_prgDaoColBindInfo = new DAOCOLUMNBINDING[m_nFields];
  4887.         memset(m_prgDaoColBindInfo, 0, sizeof(DAOCOLUMNBINDING) * m_nFields);
  4888.         m_pulColumnLengths = new DWORD[m_nFields];
  4889.         memset(m_pulColumnLengths, 0, sizeof(DWORD) * m_nFields);
  4890.  
  4891.         m_pbFieldFlags = new BYTE[m_nFields];
  4892.         memset(m_pbFieldFlags, 0, m_nFields);
  4893.  
  4894.         m_DaoFetchRows.cRowsRequested = 1;
  4895.         m_DaoFetchRows.dwFlags = DAOROWFETCH_BINDABSOLUTE;
  4896.         m_DaoFetchRows.pData = NULL;
  4897.  
  4898.         // Allocate the index map
  4899.         ASSERT(m_pMapFieldIndex == NULL);
  4900.         m_pMapFieldIndex = new CMapPtrToPtr;
  4901.  
  4902.         CDaoFieldExchange fx(CDaoFieldExchange::BindField, this);
  4903.         DoFieldExchange(&fx);
  4904.     }
  4905. }
  4906.  
  4907. void CDaoRecordset::BindParameters()
  4908. {
  4909.     ASSERT_VALID(this);
  4910.  
  4911.     if (m_nParams > 0)
  4912.     {
  4913.         // Since Jet treats non-bindable names as implicit parameters
  4914.         // this should catch some SQL syntax errors that would otherwise
  4915.         // appear to be uninitialized parameters.
  4916.         ASSERT(m_pQueryDef->GetParameterCount() == m_nParams);
  4917.  
  4918.         CDaoFieldExchange fx(CDaoFieldExchange::BindParam, this);
  4919.         DoFieldExchange(&fx);
  4920.     }
  4921. }
  4922.  
  4923. void CDaoRecordset::Fixup()
  4924. {
  4925.     ASSERT_VALID(this);
  4926.  
  4927.     CDaoFieldExchange fx(CDaoFieldExchange::Fixup, this);
  4928.     DoFieldExchange(&fx);
  4929. }
  4930.  
  4931. void CDaoRecordset::AllocCache()
  4932. {
  4933.     ASSERT_VALID(this);
  4934.  
  4935.     // Do nothing if caching disabled by master switch
  4936.     if (m_bCheckCacheForDirtyFields && m_nFields > 0 &&
  4937.         m_pMapFieldCache == NULL)
  4938.     {
  4939.         m_pMapFieldCache = new CMapPtrToPtr;
  4940.  
  4941.         CDaoFieldExchange fx(CDaoFieldExchange::AllocCache, this);
  4942.         DoFieldExchange(&fx);
  4943.     }
  4944. }
  4945.  
  4946. void CDaoRecordset::StoreFields()
  4947. {
  4948.     ASSERT_VALID(this);
  4949.  
  4950.     // Do nothing if caching disabled by master switch
  4951.     if (m_bCheckCacheForDirtyFields && m_nFields > 0)
  4952.     {
  4953.         ASSERT(m_pMapFieldCache != NULL);
  4954.         CDaoFieldExchange fx(CDaoFieldExchange::StoreField, this);
  4955.         DoFieldExchange(&fx);
  4956.     }
  4957. }
  4958.  
  4959. void CDaoRecordset::LoadFields()
  4960. {
  4961.     ASSERT_VALID(this);
  4962.  
  4963.     // Do nothing if caching disabled by master switch
  4964.     if (m_bCheckCacheForDirtyFields && m_nFields > 0)
  4965.     {
  4966.         CDaoFieldExchange fx(CDaoFieldExchange::LoadField, this);
  4967.         DoFieldExchange(&fx);
  4968.  
  4969.         // Clear the dirty status flags
  4970.         SetFieldDirty(NULL, FALSE);
  4971.     }
  4972. }
  4973.  
  4974. void CDaoRecordset::FreeCache()
  4975. {
  4976.     ASSERT_VALID(this);
  4977.  
  4978.     // Do nothing if caching disabled by master switch
  4979.     if (m_bCheckCacheForDirtyFields && m_nFields > 0 &&
  4980.         m_pMapFieldCache != NULL)
  4981.     {
  4982.         // Free up dynamically allocated mem in cache
  4983.         CDaoFieldExchange fx(CDaoFieldExchange::FreeCache, this);
  4984.  
  4985.         // Delete any cached data
  4986.         void* pvKey;
  4987.         void* pvObject;
  4988.         POSITION pos = m_pMapFieldCache->GetStartPosition();
  4989.         while (pos != NULL)
  4990.         {
  4991.             m_pMapFieldCache->GetNextAssoc(pos, pvKey, pvObject);
  4992.             fx.DeleteCacheValue((CDaoFieldCache*)pvObject,
  4993.                 ((CDaoFieldCache*)pvObject)->m_nDataType);
  4994.         }
  4995.         m_pMapFieldCache->RemoveAll();
  4996.  
  4997.         delete m_pMapFieldCache;
  4998.         m_pMapFieldCache = NULL;
  4999.     }
  5000. }
  5001.  
  5002. void CDaoRecordset::MarkForAddNew()
  5003. {
  5004.     ASSERT_VALID(this);
  5005.  
  5006.     CDaoFieldExchange fx(CDaoFieldExchange::MarkForAddNew, this);
  5007.     DoFieldExchange(&fx);
  5008. }
  5009.  
  5010. void CDaoRecordset::MarkForEdit()
  5011. {
  5012.     ASSERT_VALID(this);
  5013.  
  5014.     CDaoFieldExchange fx(CDaoFieldExchange::MarkForEdit, this);
  5015.     DoFieldExchange(&fx);
  5016. }
  5017.  
  5018. int CDaoRecordset::GetFieldIndex(void* pv)
  5019. {
  5020.     ASSERT_VALID(this);
  5021.     ASSERT(m_pMapFieldIndex != NULL);
  5022.  
  5023.     void* pvIndex;
  5024.  
  5025.     if (!m_pMapFieldIndex->Lookup(pv, pvIndex))
  5026.         return AFX_DAO_DATA_NOT_FOUND;
  5027.     else
  5028.         // Index was stored rather than ptr, make it 0-based
  5029.         return ((int)pvIndex) - 1;
  5030. }
  5031.  
  5032. void CDaoRecordset::SetDirtyFields()
  5033. {
  5034.     ASSERT_VALID(this);
  5035.  
  5036.     if (m_pDAOFields == NULL)
  5037.         InitFieldsCollection();
  5038.  
  5039.     CDaoFieldExchange fx(CDaoFieldExchange::SetDirtyField, this);
  5040.     DoFieldExchange(&fx);
  5041. }
  5042.  
  5043. void CDaoRecordset::SetCursorAttributes()
  5044. {
  5045.     ASSERT_VALID(this);
  5046.  
  5047.     m_bScrollable = !(m_nOptions & dbForwardOnly);
  5048.     m_bAppendable = CanUpdate() ||
  5049.         (!(m_nOptions & dbReadOnly) && (m_nOptions & dbAppendOnly));
  5050. }
  5051.  
  5052. void CDaoRecordset::GetDataAndFixupNulls()
  5053. {
  5054.     ASSERT_VALID(this);
  5055.  
  5056.     // Don't need to do anything if no fields bound
  5057.     if (m_nFields > 0)
  5058.     {
  5059.         if (IsEOF() || IsBOF())
  5060.         {
  5061.             // If no current record, simple mark fields NULL
  5062.             if (m_nFields > 0)
  5063.                 SetFieldNull(NULL);
  5064.         }
  5065.         else
  5066.         {
  5067.             if (m_pICDAORecordsetGetRows == NULL)
  5068.             {
  5069.                 DAO_CHECK(m_pDAORecordset->QueryInterface(
  5070.                     IID_ICDAORecordset, (void**)&m_pICDAORecordsetGetRows));
  5071.             }
  5072.  
  5073.             // Call GetRows to fill in the bound data
  5074.             SCODE scode = m_pICDAORecordsetGetRows->GetRows(
  5075.                 0, m_nFields, m_prgDaoColBindInfo,
  5076.                 m_cbFixedLengthFields, &m_DaoFetchRows);
  5077.  
  5078.             // Check for GetRows specific errors
  5079.             //  This is necessary as ICDAORecordset::GetRows
  5080.             //  errors are not appended to DAO errors collection
  5081.             if (FAILED(scode))
  5082.                 ThrowGetRowsDaoException(scode);
  5083.  
  5084.             // Check to see if row deleted as it is just warning
  5085.             m_bDeleted = scode == S_RECORDDELETED;
  5086.  
  5087.             // Reset the status array
  5088.             ClearFieldStatusFlags();
  5089.  
  5090.             // Fixup Null fields
  5091.             Fixup();
  5092.         }
  5093.     }
  5094. }
  5095.  
  5096. BOOL CDaoRecordset::IsFieldStatusDirty(UINT nField)
  5097. {
  5098.     ASSERT_VALID(this);
  5099.  
  5100.     return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_DIRTY) ==
  5101.         AFX_DAO_FIELD_FLAG_DIRTY);
  5102. }
  5103.  
  5104. void CDaoRecordset::SetDirtyFieldStatus(UINT nField)
  5105. {
  5106.     ASSERT_VALID(this);
  5107.  
  5108.     m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_DIRTY;
  5109. }
  5110.  
  5111. void CDaoRecordset::ClearDirtyFieldStatus(UINT nField)
  5112. {
  5113.     ASSERT_VALID(this);
  5114.  
  5115.     m_pbFieldFlags[nField] &= ~AFX_DAO_FIELD_FLAG_DIRTY;
  5116. }
  5117.  
  5118. BOOL CDaoRecordset::IsFieldStatusNull(UINT nField)
  5119. {
  5120.     ASSERT_VALID(this);
  5121.  
  5122.     return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_NULL) ==
  5123.         AFX_DAO_FIELD_FLAG_NULL);
  5124. }
  5125.  
  5126. void CDaoRecordset::SetNullFieldStatus(UINT nField)
  5127. {
  5128.     ASSERT_VALID(this);
  5129.  
  5130.     m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_NULL;
  5131. }
  5132.  
  5133. void CDaoRecordset::ClearNullFieldStatus(UINT nField)
  5134. {
  5135.     ASSERT_VALID(this);
  5136.  
  5137.     m_pbFieldFlags[nField] &= ~AFX_DAO_FIELD_FLAG_NULL;
  5138. }
  5139.  
  5140. BOOL CDaoRecordset::IsFieldStatusNullable(UINT nField)
  5141. {
  5142.     ASSERT_VALID(this);
  5143.  
  5144.     return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_NULLABLE) ==
  5145.         AFX_DAO_FIELD_FLAG_NULLABLE);
  5146. }
  5147.  
  5148. void CDaoRecordset::SetNullableFieldStatus(UINT nField)
  5149. {
  5150.     ASSERT_VALID(this);
  5151.  
  5152.     m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_NULLABLE;
  5153. }
  5154.  
  5155. BOOL CDaoRecordset::IsFieldStatusNullableKnown(UINT nField)
  5156. {
  5157.     ASSERT_VALID(this);
  5158.  
  5159.     return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_NULLABLE_KNOWN)
  5160.         == AFX_DAO_FIELD_FLAG_NULLABLE_KNOWN);
  5161. }
  5162.  
  5163. void CDaoRecordset::SetNullableKnownFieldStatus(UINT nField)
  5164. {
  5165.     ASSERT_VALID(this);
  5166.  
  5167.     m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_NULLABLE_KNOWN;
  5168. }
  5169.  
  5170. void CDaoRecordset::ClearFieldStatusFlags()
  5171. {
  5172.     ASSERT_VALID(this);
  5173.  
  5174.     memset(m_pbFieldFlags, 0, m_nFields);
  5175. }
  5176.  
  5177. BOOL CDaoRecordset::IsMatch()
  5178. {
  5179.     ASSERT_VALID(this);
  5180.     ASSERT(IsOpen());
  5181.  
  5182.     short nNoMatch;
  5183.  
  5184.     DAO_CHECK(m_pDAORecordset->get_NoMatch(&nNoMatch));
  5185.  
  5186.     // Return TRUE if NoMatch is FALSE
  5187.     return nNoMatch == AFX_DAO_FALSE;
  5188. }
  5189.  
  5190. void AFX_CDECL CDaoRecordset::StripBrackets(LPCTSTR lpszSrc, LPTSTR lpszDest)
  5191. {
  5192.     while (*lpszSrc != '\0')
  5193.     {
  5194.         // Ignore all brackets
  5195.         while (*lpszSrc == '[' || *lpszSrc == ']')
  5196.             lpszSrc = _tcsinc(lpszSrc);
  5197.  
  5198.         // Quit if at the end of the string
  5199.         if (*lpszSrc == '\0')
  5200.             break;
  5201.  
  5202.         // Copy the data and increment the buffers
  5203.         if (_istlead(*lpszSrc))
  5204.             *lpszDest++ = *lpszSrc++;
  5205.         *lpszDest++ = *lpszSrc++;
  5206.     }
  5207.  
  5208.     // Add the trailing '\0'
  5209.     *lpszDest = '\0';
  5210. }
  5211.  
  5212. void CDaoRecordset::ThrowDaoException(int nAfxDaoError)
  5213. {
  5214.     ASSERT_VALID(this);
  5215.  
  5216.     AfxThrowDaoException(nAfxDaoError);
  5217. }
  5218.  
  5219. #ifdef _DEBUG
  5220. void CDaoRecordset::AssertValid() const
  5221. {
  5222.     CObject::AssertValid();
  5223. }
  5224.  
  5225. void CDaoRecordset::Dump(CDumpContext& dc) const
  5226. {
  5227.     ASSERT_VALID(this);
  5228.  
  5229.     CObject::Dump(dc);
  5230.  
  5231.     dc << "\nm_bOpen = " << m_bOpen;
  5232.     dc << "\nm_bAppendable = " << m_bAppendable;
  5233.     dc << "\nm_bScrollable = " << m_bScrollable;
  5234.     dc << "\nm_bDeleted = " << m_bDeleted;
  5235.  
  5236.     dc << "\nm_nOpenType = " << m_nOpenType;
  5237.     dc << "\nm_nDefaultType = " << m_nDefaultType;
  5238.     dc << "\nm_nOptions = " << m_nOptions;
  5239.  
  5240.     dc << "\nm_strSQL = " << m_strSQL;
  5241.     dc << "\nm_strFilter = " << m_strFilter;
  5242.     dc << "\nm_strSort = " << m_strSort;
  5243.     dc << "\nm_strRequerySQL = " << m_strRequerySQL;
  5244.     dc << "\nm_strRequeryFilter = " << m_strRequeryFilter;
  5245.     dc << "\nm_strRequerySort = " << m_strRequerySort;
  5246.  
  5247.     dc << "\nm_nFields = " << m_nFields;
  5248.     dc << "\nm_nParams = " << m_nParams;
  5249.  
  5250.     dc << "\nm_bCheckCacheForDirtyFields = " << m_bCheckCacheForDirtyFields;
  5251.     dc << "\nm_nStatus = " << m_nStatus;
  5252.  
  5253.     dc << "\n";
  5254. }
  5255. #endif //_DEBUG
  5256.  
  5257. //////////////////////////////////////////////////////////////////////////
  5258. // Helpers - implementation
  5259. void AFX_CDECL AfxGetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo,
  5260.     DWORD dwInfoOptions)
  5261. {
  5262.     ASSERT(pDAOField != NULL);
  5263.     ASSERT(dwInfoOptions != 0);
  5264.  
  5265.     COleVariant var;
  5266.     short nBool;
  5267.  
  5268.     // Always fetch the Primary properties
  5269.     if (dwInfoOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  5270.     {
  5271.         DAO_CHECK(pDAOField->get_Name(&V_BSTR(&var)));
  5272.         var.vt = VT_BSTR;
  5273.         fieldinfo.m_strName = V_BSTRT(&var);
  5274.         var.Clear();
  5275.  
  5276.         DAO_CHECK(pDAOField->get_Type(&fieldinfo.m_nType));
  5277.  
  5278.         DAO_CHECK(pDAOField->get_Size(&fieldinfo.m_lSize));
  5279.  
  5280.         DAO_CHECK(pDAOField->get_Attributes(&fieldinfo.m_lAttributes));
  5281.     }
  5282.  
  5283.     if (dwInfoOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
  5284.     {
  5285.         DAO_CHECK(pDAOField->get_OrdinalPosition(
  5286.             &fieldinfo.m_nOrdinalPosition));
  5287.  
  5288.         DAO_CHECK(pDAOField->get_Required(&nBool));
  5289.         fieldinfo.m_bRequired = nBool == AFX_DAO_TRUE;
  5290.  
  5291.         DAO_CHECK(pDAOField->get_AllowZeroLength(&nBool));
  5292.         fieldinfo.m_bAllowZeroLength = nBool == AFX_DAO_TRUE;
  5293.  
  5294.         DAO_CHECK(pDAOField->get_CollatingOrder(
  5295.             &fieldinfo.m_lCollatingOrder));
  5296.  
  5297.         DAO_CHECK(pDAOField->get_SourceField(&V_BSTR(&var)));
  5298.         var.vt = VT_BSTR;
  5299.         fieldinfo.m_strSourceField = V_BSTRT(&var);
  5300.         var.Clear();
  5301.  
  5302.         DAO_CHECK(pDAOField->get_SourceTable(&V_BSTR(&var)));
  5303.         var.vt = VT_BSTR;
  5304.         fieldinfo.m_strSourceTable = V_BSTRT(&var);
  5305.         var.Clear();
  5306.  
  5307.         TRY
  5308.         {
  5309.             DAO_CHECK(pDAOField->get_ForeignName(&V_BSTR(&var)));
  5310.             var.vt = VT_BSTR;
  5311.             fieldinfo.m_strForeignName = V_BSTRT(&var);
  5312.             var.Clear();
  5313.         }
  5314.         CATCH(CDaoException, e)
  5315.         {
  5316.             // If this property not appropriate, set foreign name empty
  5317.             if (e->m_scode != E_DAO_IllegalOperation)
  5318.                 THROW_LAST();
  5319.             else
  5320.             {
  5321.                 fieldinfo.m_strForeignName.Empty();
  5322.                 e->Delete();
  5323.             }
  5324.         }
  5325.         END_CATCH
  5326.     }
  5327.  
  5328.     if (dwInfoOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
  5329.     {
  5330.         AfxGetDefaultValue(pDAOField, fieldinfo.m_strDefaultValue);
  5331.  
  5332.         DAO_CHECK(pDAOField->get_ValidationRule(&V_BSTR(&var)));
  5333.         var.vt = VT_BSTR;
  5334.         fieldinfo.m_strValidationRule = V_BSTRT(&var);
  5335.         var.Clear();
  5336.  
  5337.         DAO_CHECK(pDAOField->get_ValidationText(&V_BSTR(&var)));
  5338.         var.vt = VT_BSTR;
  5339.         fieldinfo.m_strValidationText = V_BSTRT(&var);
  5340.         var.Clear();
  5341.     }
  5342. }
  5343.  
  5344. void AFX_CDECL AfxSetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo)
  5345. {
  5346.     // Assumes name, type and size set on direct DAO CreateField call
  5347.     ASSERT(pDAOField != NULL);
  5348.  
  5349.     if (fieldinfo.m_lAttributes != 0)
  5350.         DAO_CHECK(pDAOField->put_Attributes(fieldinfo.m_lAttributes));
  5351.  
  5352.     if (fieldinfo.m_nOrdinalPosition != 0)
  5353.     {
  5354.         DAO_CHECK(pDAOField->put_OrdinalPosition(
  5355.             fieldinfo.m_nOrdinalPosition));
  5356.     }
  5357.  
  5358.     if (fieldinfo.m_bRequired)
  5359.         DAO_CHECK(pDAOField->put_Required(AFX_DAO_TRUE));
  5360.  
  5361.     if (fieldinfo.m_bAllowZeroLength)
  5362.         DAO_CHECK(pDAOField->put_AllowZeroLength(AFX_DAO_TRUE));
  5363.  
  5364.     if (!fieldinfo.m_strForeignName.IsEmpty())
  5365.     {
  5366.         COleVariant var(fieldinfo.m_strForeignName, VT_BSTRT);
  5367.         DAO_CHECK(pDAOField->put_ForeignName(V_BSTR(&var)));
  5368.     }
  5369.  
  5370.     if (!fieldinfo.m_strValidationRule.IsEmpty())
  5371.     {
  5372.         COleVariant var(fieldinfo.m_strValidationRule, VT_BSTRT);
  5373.         DAO_CHECK(pDAOField->put_ValidationRule(V_BSTR(&var)));
  5374.     }
  5375.  
  5376.     if (!fieldinfo.m_strValidationText.IsEmpty())
  5377.     {
  5378.         COleVariant var(fieldinfo.m_strValidationText, VT_BSTRT);
  5379.         DAO_CHECK(pDAOField->put_ValidationText(V_BSTR(&var)));
  5380.     }
  5381.  
  5382.     if (!fieldinfo.m_strDefaultValue.IsEmpty())
  5383.     {
  5384.         AfxSetDefaultValue(pDAOField, fieldinfo.m_strDefaultValue);
  5385.     }
  5386. }
  5387.  
  5388. void AFX_CDECL AfxGetDefaultValue(DAOField* pDAOField, CString& strDefaultValue)
  5389. {
  5390.     COleVariant var;
  5391.     BYTE bUseDao = _AfxDetermineDaoVersion();
  5392.  
  5393.     if (bUseDao == 35 || bUseDao == 36)
  5394.     {
  5395.         // Call the DAO 3.5/3.6 method
  5396.         DAO_CHECK(pDAOField->get_DefaultValue(&var));
  5397.     }
  5398.     else
  5399.     {
  5400.         // Call DAO 3.0 method
  5401.         // get_DefaultValue takes BSTR* param not VARIANT*
  5402.         HRESULT (STDMETHODCALLTYPE DAOField::*pMethod)(BSTR*) = (HRESULT (STDMETHODCALLTYPE DAOField::*)(BSTR*))pDAOField->get_DefaultValue;
  5403.         DAO_CHECK((pDAOField->*pMethod)(&V_BSTR(&var)));
  5404.         var.vt = VT_BSTR;
  5405.     }
  5406.  
  5407.     strDefaultValue = V_BSTRT(&var);
  5408.     var.Clear();
  5409. }
  5410.  
  5411. void AFX_CDECL AfxSetDefaultValue(DAOField* pDAOField, CString& strDefaultValue)
  5412. {
  5413.     COleVariant var(strDefaultValue, VT_BSTRT);
  5414.     BYTE bUseDao = _AfxDetermineDaoVersion();
  5415.  
  5416.     if (bUseDao == 35 || bUseDao == 36)
  5417.     {
  5418.         // Call DAO 3.5/3.6 version
  5419.         DAO_CHECK(pDAOField->put_DefaultValue(var));
  5420.     }
  5421.     else
  5422.     {
  5423.         // Call DAO 3.0 method
  5424.         // put_DefaultValue takes BSTR param not VARIANT
  5425.         HRESULT (STDMETHODCALLTYPE DAOField::*pMethod)(BSTR) = (HRESULT (STDMETHODCALLTYPE DAOField::*)(BSTR))pDAOField->put_DefaultValue;
  5426.         DAO_CHECK((pDAOField->*pMethod)(V_BSTR(&var)));
  5427.     }
  5428. }
  5429.  
  5430. void AFX_CDECL AfxGetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo,
  5431.     DWORD dwInfoOptions)
  5432. {
  5433.     ASSERT(pDAOIndex != NULL);
  5434.     ASSERT(dwInfoOptions != 0);
  5435.  
  5436.     COleVariant var;
  5437.     short nBool;
  5438.  
  5439.     if (dwInfoOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
  5440.     {
  5441.         DAO_CHECK(pDAOIndex->get_Name(&V_BSTR(&var)));
  5442.         var.vt = VT_BSTR;
  5443.         indexinfo.m_strName = V_BSTRT(&var);
  5444.         var.Clear();
  5445.  
  5446.         AfxGetIndexFieldInfo(pDAOIndex, indexinfo);
  5447.     }
  5448.  
  5449.     if (dwInfoOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
  5450.     {
  5451.         DAO_CHECK(pDAOIndex->get_Primary(&nBool));
  5452.         indexinfo.m_bPrimary = nBool == AFX_DAO_TRUE;
  5453.  
  5454.         DAO_CHECK(pDAOIndex->get_Unique(&nBool));
  5455.         indexinfo.m_bUnique = nBool == AFX_DAO_TRUE;
  5456.  
  5457.         DAO_CHECK(pDAOIndex->get_Clustered(&nBool));
  5458.         indexinfo.m_bClustered = nBool == AFX_DAO_TRUE;
  5459.  
  5460.         DAO_CHECK(pDAOIndex->get_IgnoreNulls(&nBool));
  5461.         indexinfo.m_bIgnoreNulls = nBool == AFX_DAO_TRUE;
  5462.  
  5463.         DAO_CHECK(pDAOIndex->get_Required(&nBool));
  5464.         indexinfo.m_bRequired = nBool == AFX_DAO_TRUE;
  5465.  
  5466.         DAO_CHECK(pDAOIndex->get_Foreign(&nBool));
  5467.         indexinfo.m_bForeign = nBool == AFX_DAO_TRUE;
  5468.     }
  5469.  
  5470.     if (dwInfoOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
  5471.     {
  5472.         DAO_CHECK(pDAOIndex->get_DistinctCount(
  5473.             &indexinfo.m_lDistinctCount));
  5474.     }
  5475. }
  5476.  
  5477. void AFX_CDECL AfxSetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo)
  5478. {
  5479.     // Assumes name,set on direct DAO CreateIndex call
  5480.     ASSERT(pDAOIndex != NULL);
  5481.  
  5482.     AfxSetIndexFieldInfo(pDAOIndex, indexinfo);
  5483.  
  5484.     if (indexinfo.m_bPrimary)
  5485.         DAO_CHECK(pDAOIndex->put_Primary(AFX_DAO_TRUE));
  5486.  
  5487.     if (indexinfo.m_bUnique)
  5488.         DAO_CHECK(pDAOIndex->put_Unique(AFX_DAO_TRUE));
  5489.  
  5490.     if (indexinfo.m_bClustered)
  5491.         DAO_CHECK(pDAOIndex->put_Clustered(AFX_DAO_TRUE));
  5492.  
  5493.     if (indexinfo.m_bIgnoreNulls)
  5494.         DAO_CHECK(pDAOIndex->put_IgnoreNulls(AFX_DAO_TRUE));
  5495.  
  5496.     if (indexinfo.m_bRequired)
  5497.         DAO_CHECK(pDAOIndex->put_Required(AFX_DAO_TRUE));
  5498. }
  5499.  
  5500. void AFX_CDECL AfxGetIndexFields(DAOIndex* pDAOIndex,
  5501.     DAOIndexFields** ppDAOIndexFields)
  5502. {
  5503.     COleVariant var;
  5504.     BYTE bUseDao = _AfxDetermineDaoVersion();
  5505.  
  5506.     // Set the desired interface
  5507.     GUID guidIndexFields;
  5508.    if (bUseDao == 35 || bUseDao == 36)
  5509.    {
  5510.       // Use DAO 3.5/3.6
  5511. #ifdef _UNICODE
  5512.        guidIndexFields = IID_IDAOIndexFieldsW;
  5513. #else
  5514.        guidIndexFields = IID_IDAOIndexFields;
  5515. #endif
  5516.    }
  5517.    else
  5518.    {
  5519.       // Use DAO 3.0
  5520. #ifdef _UNICODE
  5521.       guidIndexFields = IID30_IDAOIndexFieldsW;
  5522. #else
  5523.       guidIndexFields = IID30_IDAOIndexFields;
  5524. #endif
  5525.    }
  5526.  
  5527.     // Get dispatch pointer to fields collection
  5528.     DAO_CHECK(pDAOIndex->get_Fields(&var));
  5529.     DAO_CHECK(var.pdispVal->QueryInterface(
  5530.         guidIndexFields, (void**)ppDAOIndexFields));
  5531. }
  5532.  
  5533. void AFX_CDECL AfxGetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo)
  5534. {
  5535.     COleVariant var;
  5536.  
  5537.     DAOIndexFields* pDAOIndexFields = NULL;
  5538.     DAOField* pDAOField = NULL;
  5539.  
  5540.     // Get the index fields collection
  5541.     AfxGetIndexFields(pDAOIndex, &pDAOIndexFields);
  5542.  
  5543.     TRY
  5544.     {
  5545.         // Get the number of fields in the index
  5546.         short nCount;
  5547.         DAO_CHECK(pDAOIndexFields->get_Count(&nCount));
  5548.  
  5549.         // Allocate or reallocate memory for array if necessary
  5550.         if (nCount != indexinfo.m_nFields)
  5551.         {
  5552.             if (indexinfo.m_nFields != 0)
  5553.             {
  5554.                 // Check that allocation is correct.
  5555.                 ASSERT(indexinfo.m_nFields == 0 ||
  5556.                     indexinfo.m_bCleanupFieldInfo);
  5557.  
  5558.                 delete[] indexinfo.m_pFieldInfos;
  5559.                 indexinfo.m_pFieldInfos = NULL;
  5560.             }
  5561.  
  5562.             // Now allocate required memory
  5563.             indexinfo.m_pFieldInfos = new CDaoIndexFieldInfo[nCount];
  5564.             indexinfo.m_bCleanupFieldInfo = TRUE;
  5565.             indexinfo.m_nFields = nCount;
  5566.         }
  5567.  
  5568.        BYTE bUseDao = _AfxDetermineDaoVersion();
  5569.  
  5570.         // Now get field info for each field
  5571.         long lAttributes;
  5572.         for (short nIndex = 0; nIndex < indexinfo.m_nFields; nIndex++)
  5573.         {
  5574.             // Set the desired interface
  5575.             GUID guidField;
  5576.  
  5577.          if (bUseDao == 35 || bUseDao == 36)
  5578.          {
  5579. #ifdef _UNICODE
  5580.                guidField = IID_IDAOFieldW;
  5581. #else
  5582.                guidField = IID_IDAOField;
  5583. #endif
  5584.          }
  5585.          else
  5586.          {
  5587. #ifdef _UNICODE
  5588.             guidField = IID30_IDAOFieldW;
  5589. #else
  5590.             guidField = IID30_IDAOField;
  5591. #endif
  5592.          }
  5593.  
  5594.             // Get the field item
  5595.             DAO_CHECK(pDAOIndexFields->get_Item(COleVariant(nIndex), &var));
  5596.             DAO_CHECK(var.pdispVal->QueryInterface(
  5597.                 guidField, (void**)&pDAOField));
  5598.             var.Clear();
  5599.  
  5600.             // Get the field name
  5601.             DAO_CHECK(pDAOField->get_Name(&V_BSTR(&var)));
  5602.             var.vt = VT_BSTR;
  5603.             indexinfo.m_pFieldInfos[nIndex].m_strName = V_BSTRT(&var);
  5604.             var.Clear();
  5605.  
  5606.             // Get the field attributes
  5607.             DAO_CHECK(pDAOField->get_Attributes(&lAttributes));
  5608.             indexinfo.m_pFieldInfos[nIndex].m_bDescending =
  5609.                 (lAttributes & dbDescending);
  5610.  
  5611.             // Release and reset the field object
  5612.             pDAOField->Release();
  5613.             pDAOField = NULL;
  5614.         }
  5615.  
  5616.         // Release the index fields object
  5617.         pDAOIndexFields->Release();
  5618.     }
  5619.     CATCH_ALL(e)
  5620.     {
  5621.         // Release the field object if necessary
  5622.         if (pDAOField != NULL)
  5623.             pDAOField->Release();
  5624.  
  5625.         // Must always release index fields collection
  5626.         pDAOIndexFields->Release();
  5627.         THROW_LAST();
  5628.     }
  5629.     END_CATCH_ALL
  5630. }
  5631.  
  5632. void AFX_CDECL AfxSetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo)
  5633. {
  5634.     COleVariant var;
  5635.     long lAttributes;
  5636.  
  5637.     DAOIndexFields* pDAOIndexFields = NULL;
  5638.     DAOField* pDAOField = NULL;
  5639.  
  5640.     // Get the index fields collection
  5641.     AfxGetIndexFields(pDAOIndex, &pDAOIndexFields);
  5642.  
  5643.     TRY
  5644.     {
  5645.         for (int nIndex = 0; nIndex < indexinfo.m_nFields; nIndex++)
  5646.         {
  5647.             // Create the field and set the name
  5648.             DAO_CHECK(pDAOIndex->CreateField(
  5649.                 COleVariant(indexinfo.m_pFieldInfos[nIndex].m_strName, VT_BSTRT),
  5650.                 _afxOptionalVariant, _afxOptionalVariant, &pDAOField));
  5651.  
  5652.             // Set the descending property
  5653.             if (indexinfo.m_pFieldInfos[nIndex].m_bDescending)
  5654.                 lAttributes = dbDescending;
  5655.             else
  5656.                 lAttributes = 0;
  5657.             DAO_CHECK(pDAOField->put_Attributes(lAttributes));
  5658.  
  5659.             // Append field to collection, release and reset
  5660.             pDAOIndexFields->Append(pDAOField);
  5661.             pDAOField->Release();
  5662.             pDAOField = NULL;
  5663.         }
  5664.  
  5665.         // Always release the index fields object
  5666.         pDAOIndexFields->Release();
  5667.     }
  5668.     CATCH_ALL(e)
  5669.     {
  5670.         if (pDAOField != NULL)
  5671.             pDAOField->Release();
  5672.  
  5673.         pDAOIndexFields->Release();
  5674.         THROW_LAST();
  5675.     }
  5676.     END_CATCH_ALL
  5677. }
  5678.  
  5679. //////////////////////////////////////////////////////////////////////////////
  5680. // GetRows helper
  5681. void AFX_CDECL ThrowGetRowsDaoException(SCODE scode)
  5682. {
  5683.     switch (scode)
  5684.     {
  5685.         case E_OUTOFMEMORY:
  5686.             AfxThrowMemoryException();
  5687.  
  5688.         default:
  5689.             AfxThrowDaoException(NO_AFX_DAO_ERROR, scode);
  5690.  
  5691.         // These are only (known) DAO 3.0 GetRows errors
  5692.         case E_ROWTOOSHORT:
  5693.         case E_BADBINDINFO:
  5694.         case E_COLUMNUNAVAILABLE:
  5695.             break;
  5696.     }
  5697.  
  5698.     CDaoException* pException;
  5699.     pException = new CDaoException;
  5700.     pException->m_pErrorInfo = new CDaoErrorInfo;
  5701.  
  5702.     // Fill out the DAO error info struct
  5703.     pException->m_scode = scode;
  5704.     pException->m_pErrorInfo->m_strSource = _T("ICDAORecordset.GetRows");
  5705.     pException->m_pErrorInfo->m_lErrorCode = LOWORD(scode);
  5706.  
  5707.     // There is no help context or help file
  5708.     pException->m_pErrorInfo->m_lHelpContext = 0;
  5709.  
  5710.     int nID = 0;
  5711.  
  5712.     if (scode == E_ROWTOOSHORT)
  5713.         nID = AFX_IDP_DAO_ROWTOOSHORT;
  5714.     else if (scode == E_BADBINDINFO)
  5715.         nID = AFX_IDP_DAO_BADBINDINFO;
  5716.     else
  5717.         nID = AFX_IDP_DAO_COLUMNUNAVAILABLE;
  5718.  
  5719.     VERIFY(pException->m_pErrorInfo->m_strDescription.LoadString(nID));
  5720.  
  5721. #ifdef _DEBUG
  5722.     if (afxTraceFlags & traceDatabase)
  5723.     {
  5724.         TRACE1("\nError Code = %d\n",
  5725.             pException->m_pErrorInfo->m_lErrorCode);
  5726.         TRACE1("Source = %s\n",
  5727.             (LPCTSTR)pException->m_pErrorInfo->m_strSource);
  5728.         TRACE1("Description = %s\n",
  5729.             (LPCTSTR)pException->m_pErrorInfo->m_strDescription);
  5730.     }
  5731. #endif
  5732.  
  5733.     THROW(pException);
  5734. }
  5735.  
  5736. //////////////////////////////////////////////////////////////////////////////
  5737. // _AFX_DAO_STATE helper
  5738. _AFX_DAO_STATE* AFX_CDECL AfxGetDaoState()
  5739. {
  5740.     // The DAO state is store in the module state
  5741.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  5742.     _AFX_DAO_STATE* pDaoState = pModuleState->m_pDaoState;
  5743.  
  5744.     // Allocate a new DAO state if necessary
  5745.     if (pDaoState == NULL)
  5746.     {
  5747.         pDaoState = new _AFX_DAO_STATE;
  5748.         pModuleState->m_pDaoState = pDaoState;
  5749.     }
  5750.     return pDaoState;
  5751. }
  5752.  
  5753.  
  5754. //////////////////////////////////////////////////////////////////////////////
  5755. // DAODBEngine helpers
  5756. void AFXAPI AfxDaoInit()
  5757. {
  5758.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  5759.  
  5760.     // Attempt to initialize OLE component objects
  5761.     //  (use default IMalloc allocator)
  5762.     DAO_CHECK_ERROR(::CoInitialize(NULL),
  5763.         AFX_DAO_ERROR_ENGINE_INITIALIZATION);
  5764.     pDaoState->m_bOleInitialized = TRUE;
  5765.  
  5766.     // Hook AfxDaoTerm to CWinApp, otherwise explicit AfxDaoTerm call req'd
  5767.     CWinApp* pApp = AfxGetApp();
  5768.     if (pApp != NULL)
  5769.         pApp->m_lpfnDaoTerm = AfxDaoTerm;
  5770.  
  5771.     BYTE bUseDao = _AfxDetermineDaoVersion();
  5772.  
  5773.     CLSID clsidEngine;
  5774.     COleVariant varKey;
  5775.     GUID guidEngine;
  5776.  
  5777.     // Set the interface type
  5778. #ifdef _UNICODE
  5779.             guidEngine = IID_IDAODBEngineW;
  5780. #else
  5781.             guidEngine = IID_IDAODBEngine;
  5782. #endif
  5783.  
  5784.     // DAO 3.5 and 3.6 runtime key
  5785.     varKey = _T("mbmabptebkjcdlgtjmskjwtsdhjbmkmwtrak");
  5786.  
  5787.     switch (bUseDao)
  5788.     {
  5789.         case 35:
  5790.             // Use DAO 3.5
  5791.             clsidEngine = CLSID35_CDAODBEngine;
  5792.             break;
  5793.  
  5794.         case 30:
  5795.             // Use DAO 3.0
  5796.             clsidEngine = CLSID30_CDAODBEngine;
  5797.  
  5798.             // DAO 3.0 runtime key
  5799.             varKey = _T("mjgcqcejfchcijecpdhckcdjqigdejfccjri");
  5800.  
  5801.             // Set the interface type
  5802. #ifdef _UNICODE
  5803.             guidEngine = IID30_IDAODBEngineW;
  5804. #else
  5805.             guidEngine = IID30_IDAODBEngine;
  5806. #endif
  5807.             break;
  5808.  
  5809.         case 36:
  5810.             // Use DAO 3.6
  5811.             clsidEngine = CLSID_CDAODBEngine;
  5812.             break;
  5813.  
  5814.         default:
  5815.             ASSERT(FALSE);
  5816.     }
  5817.  
  5818.     LPCLASSFACTORY2 pCF2;
  5819.     DAO_CHECK_ERROR(::CoGetClassObject(clsidEngine,
  5820.         CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory2, (LPVOID*)&pCF2),
  5821.         AFX_DAO_ERROR_ENGINE_INITIALIZATION);
  5822.  
  5823.     TRY
  5824.     {
  5825.         DAO_CHECK_ERROR(pCF2->CreateInstanceLic( NULL, NULL, guidEngine,
  5826.             V_BSTR(&varKey), (LPVOID*)&pDaoState->m_pDAODBEngine),
  5827.             AFX_DAO_ERROR_ENGINE_INITIALIZATION);
  5828.     }
  5829.     CATCH_ALL(e)
  5830.     {
  5831.         pCF2->Release();
  5832.         THROW_LAST();
  5833.     }
  5834.     END_CATCH_ALL
  5835.  
  5836.     pCF2->Release();
  5837. }
  5838.  
  5839. DAODBEngine* AFXAPI AfxDaoGetEngine()
  5840. {
  5841.     // Return DAODBEngine object for direct access
  5842.     return AfxGetDaoState()->m_pDAODBEngine;
  5843. }
  5844.  
  5845. void AFXAPI AfxDaoTerm()
  5846. {
  5847.     _AFX_DAO_STATE* pDaoState = AfxGetDaoState();
  5848.  
  5849.     // Close any CDaoWorkspaces left around
  5850.     void* pvKey;
  5851.     void* pvObject;
  5852.     POSITION pos = pDaoState->m_mapWorkspaces.GetStartPosition();
  5853.     while (pos != NULL)
  5854.     {
  5855.         pDaoState->m_mapWorkspaces.GetNextAssoc(pos, pvKey, pvObject);
  5856.         ((CDaoWorkspace*)pvObject)->Close();
  5857.     }
  5858.     pDaoState->m_mapWorkspaces.RemoveAll();
  5859.  
  5860.     // Clean up engine object if necessary
  5861.     if (pDaoState->m_pDAODBEngine != NULL)
  5862.     {
  5863.         pDaoState->m_pDAODBEngine->Release();
  5864.         pDaoState->m_pDAODBEngine = NULL;
  5865.     }
  5866.  
  5867.     // Shutdown OLE component objects if necessary
  5868.     if (pDaoState->m_bOleInitialized)
  5869.     {
  5870.         ::CoUninitialize();
  5871.         pDaoState->m_bOleInitialized = FALSE;
  5872.     }
  5873.  
  5874.     // If hooked up to CWinApp, make sure to unhook
  5875.     CWinApp* pApp = AfxGetApp();
  5876.     if (pApp != NULL)
  5877.         pApp->m_lpfnDaoTerm = NULL;
  5878. }
  5879.  
  5880.  
  5881. //////////////////////////////////////////////////////////////////////////////
  5882. // Inline function declarations expanded out-of-line
  5883.  
  5884. #ifndef _AFX_ENABLE_INLINES
  5885.  
  5886. static char _szAfxDaoInl[] = "afxdao.inl";
  5887. #undef THIS_FILE
  5888. #define THIS_FILE _szAfxDaoInl
  5889. #define _AFXDAOCORE_INLINE
  5890. #include "afxdao.inl"
  5891.  
  5892. #endif
  5893.  
  5894. #ifdef AFX_INIT_SEG
  5895. #pragma code_seg(AFX_INIT_SEG)
  5896. #endif
  5897.  
  5898. #pragma warning(disable: 4074)
  5899. #pragma init_seg(lib)
  5900.  
  5901. /////////////////////////////////////////////////////////////////////////////
  5902.