home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / DAOCORE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-11  |  131.4 KB  |  5,881 lines

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