home *** CD-ROM | disk | FTP | other *** search
/ Looney Tunes Photo Fun / LooneyTunesPhotoFun.iso / Daosdk / DISK4 / DAOSDK.1 / qddoc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-06  |  11.2 KB  |  492 lines

  1. // qdDoc.cpp : implementation of the CQdDoc class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "MultThrd.h"
  6.  
  7. #include "qdDoc.h"
  8. #include "qdView.h"
  9.  
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15.  
  16. void ExecuteQueryDef(VOID *pv);
  17.  
  18. typedef struct _THREADPARAM
  19. {
  20.     BOOL fMarshall;    //TRUE -> pstm is valid, FALSE -> pqd is valid
  21.     LPSTREAM pstmQD;
  22.     CdbQueryDef *pqd;
  23.     LPSTREAM pstmDBEN;
  24.     CdbDBEngine *pdben;
  25.     CGridCtrl *pgrid;
  26. } THREAD_PARAM;
  27.  
  28. /////////////////////////////////////////////////////////////////////////////
  29. // CQdDoc
  30.  
  31. IMPLEMENT_DYNCREATE(CQdDoc, CDocument)
  32.  
  33. BEGIN_MESSAGE_MAP(CQdDoc, CDocument)
  34.     //{{AFX_MSG_MAP(CQdDoc)
  35.     ON_COMMAND(ID_FILE_OPENJET, OnFileOpenJet)
  36.     ON_COMMAND(ID_FILE_OPENODBC, OnFileOpenODBC)
  37.     //}}AFX_MSG_MAP
  38. END_MESSAGE_MAP()
  39.  
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CQdDoc construction/destruction
  42.  
  43. CQdDoc::CQdDoc()
  44. {
  45.     m_pdb = NULL;
  46.     m_pwksp = NULL;
  47.     m_pdben = NULL;
  48. }
  49.  
  50. CQdDoc::~CQdDoc()
  51. {
  52.     //If a Database already exists, close it down
  53.     if (m_pdb)
  54.     {
  55.         m_pdb->Close();
  56.         delete m_pdb;
  57.         m_pdb = NULL;
  58.     }
  59.  
  60.     //If a Workspace is open, close it down
  61.     if (m_pwksp)
  62.     {
  63.         m_pwksp->Close();
  64.         delete m_pwksp;
  65.         m_pwksp = NULL;
  66.     }
  67.  
  68.     if (m_pdben)
  69.         delete m_pdben;
  70. }
  71.  
  72. BOOL CQdDoc::OnNewDocument()
  73. {
  74.     if (!CDocument::OnNewDocument())
  75.         return FALSE;
  76.  
  77.     // TODO: add reinitialization code here
  78.     // (SDI documents will reuse this document)
  79.  
  80.     return TRUE;
  81. }
  82.  
  83. /////////////////////////////////////////////////////////////////////////////
  84. // CQdDoc serialization
  85.  
  86. void CQdDoc::Serialize(CArchive& ar)
  87. {
  88.     if (ar.IsStoring())
  89.     {
  90.         // TODO: add storing code here
  91.     }
  92.     else
  93.     {
  94.         // TODO: add loading code here
  95.     }
  96. }
  97.  
  98. /////////////////////////////////////////////////////////////////////////////
  99. // CQdDoc diagnostics
  100.  
  101. #ifdef _DEBUG
  102. void CQdDoc::AssertValid() const
  103. {
  104.     CDocument::AssertValid();
  105. }
  106.  
  107. void CQdDoc::Dump(CDumpContext& dc) const
  108. {
  109.     CDocument::Dump(dc);
  110. }
  111. #endif //_DEBUG
  112.  
  113. /////////////////////////////////////////////////////////////////////////////
  114. // CQdDoc commands
  115.  
  116. void CQdDoc::OnFileOpenJet() 
  117. {
  118.     static TCHAR BASED_CODE szFilter[] = _T("Jet DBs (*.mdb)|*.mdb|All Files (*.*)|*.*||");
  119.     CFileDialog dlgFile(TRUE, _T("MDB"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
  120.     long lType;
  121.     CString stDB;
  122.  
  123.     if (dlgFile.DoModal() == IDCANCEL)
  124.         return;
  125.     stDB = dlgFile.GetPathName();
  126.  
  127.     //If a Database already exists, close it down
  128.     if (m_pdb)
  129.     {
  130.         m_pdb->Close();
  131.         delete m_pdb;
  132.         m_pdb = NULL;
  133.     }
  134.  
  135.     //A workspace may already exist. If so, check the
  136.     // type. If the type is not Jet, close it down and recreate a Jet
  137.     // workspace. If it is Jet, then cool.
  138.     if (m_pwksp)
  139.     {
  140.         lType = m_pwksp->GetType();
  141.         if (lType != dbUseJet)
  142.         {
  143.             m_pwksp->Close();
  144.             delete m_pwksp;
  145.             m_pwksp = NULL;
  146.         }
  147.     }
  148.  
  149.     //Start DAO if its not already started
  150.     if (m_pdben == NULL)
  151.         m_pdben = new CdbDBEngine;
  152.  
  153.     //Create a Jet workspace if one is not already active
  154.     if (m_pwksp == NULL)
  155.     {
  156.         m_pwksp = new CdbWorkspace;
  157.         *m_pwksp = m_pdben->CreateWorkspace(_T("wsJet"), _T("admin"), _T(""), dbUseJet);
  158.     }
  159.  
  160.     //Open the database
  161.     m_pdb = new CdbDatabase();
  162.     try
  163.     {
  164.         *m_pdb = m_pwksp->OpenDatabase(stDB);
  165.  
  166.         TRACE(_T("Opened Database : %s\n"), m_pdb->GetName());
  167.         UpdateAllViews(NULL, UPDATEHINT_NEWDATABASE, m_pdb);
  168.     }
  169.     catch (CdbException)
  170.     {
  171.         CString stError;
  172.         stError.Format(_T("ERROR: %s"), m_pdben->Errors[0L].GetDescription());
  173.         AfxMessageBox(stError);
  174.         delete m_pdb;
  175.         m_pdb = NULL;
  176.     }
  177. }
  178.  
  179. void CQdDoc::OnFileOpenODBC() 
  180. {
  181.     long lType;
  182.  
  183.     //If a Database already exists, close it down
  184.     if (m_pdb)
  185.     {
  186.         m_pdb->Close();
  187.         delete m_pdb;
  188.         m_pdb = NULL;
  189.     }
  190.  
  191.     //A workspace may already exist. If so, check the
  192.     // type. If the type is not ODBC, close it down and recreate an ODBC
  193.     // workspace. If it is ODBC, then cool.
  194.     if (m_pwksp)
  195.     {
  196.         lType = m_pwksp->GetType();
  197.         if (lType != dbUseODBC)
  198.         {
  199.             m_pwksp->Close();
  200.             delete m_pwksp;
  201.             m_pwksp = NULL;
  202.         }
  203.     }
  204.  
  205.     //Start DAO if its not already started
  206.     if (m_pdben == NULL)
  207.         m_pdben = new CdbDBEngine;
  208.  
  209.     //Create an ODBC workspace if one is not already active
  210.     if (m_pwksp == NULL)
  211.     {
  212.         m_pwksp = new CdbWorkspace;
  213.         *m_pwksp = m_pdben->CreateWorkspace(_T("wsJet"), _T("admin"), _T(""), dbUseODBC);
  214.     }
  215.  
  216.     //Open the database
  217.     m_pdb = new CdbDatabase();
  218.     try
  219.     {
  220.         *m_pdb = m_pwksp->OpenDatabase(_T(""));
  221.  
  222.         TRACE(_T("Opened Database : %s\n"), m_pdb->GetName());
  223.         UpdateAllViews(NULL, UPDATEHINT_NEWDATABASE, m_pdb);
  224.     }
  225.     catch (CdbException e)
  226.     {
  227.         //Only notify the user if they didn't explicitly cancel the open
  228.         if (e.m_hr != E_DAO_OperationCanceled)
  229.         {
  230.             CString stError;
  231.             stError.Format(_T("ERROR: %s"), m_pdben->Errors[0L].GetDescription());
  232.             AfxMessageBox(stError);
  233.         }
  234.         
  235.         //Kill the new database object
  236.         delete m_pdb;
  237.         m_pdb = NULL;
  238.     }
  239. }
  240.  
  241. BOOL CQdDoc::CreateNewQD(CString &stName, CString &stSQL)
  242. {
  243.     BOOL fPassed = TRUE;
  244.     CdbQueryDef qd;
  245.     CdbConnection cn;
  246.  
  247.     try
  248.     {
  249.         if (m_pwksp->GetType() == dbUseJet)
  250.             qd = m_pdb->CreateQueryDef(stName, stSQL);
  251.         else
  252.         {
  253.             cn = m_pdb->GetConnection();
  254.             qd = cn.CreateQueryDef(stName, stSQL);
  255.         }
  256.         m_stNewQueryDef = stName;
  257.         UpdateAllViews(NULL, UPDATEHINT_NEWQUERYDEF, m_pdb);
  258.     }
  259.     catch (CdbException)
  260.     {
  261.         CString stError;
  262.         int cErr;
  263.  
  264.         cErr = m_pdben->Errors.GetCount();
  265.         stError.Format(_T("Failed to create new querydef: '%s'"), m_pdben->Errors[(long) (cErr - 1)].GetDescription());
  266.         AfxMessageBox(stError);
  267.         fPassed = FALSE;
  268.     }
  269.  
  270.     return fPassed;
  271. }
  272.  
  273. void CQdDoc::ExecuteQDs()
  274. {
  275.     POSITION pos = GetFirstViewPosition();
  276.     CQdView* pView = (CQdView *) GetNextView(pos);
  277.     int cQd, iQd;
  278.     TC_ITEM item;
  279.     CdbQueryDefs qds;
  280.     CdbQueryDef qd;
  281.     THREAD_PARAM *rgparam = NULL;
  282.     HANDLE *rghThread = NULL;
  283.     DWORD *rgtid = NULL;
  284.     DWORD dwExitCode;
  285.     BOOL fActive;
  286.     MSG msg;
  287.     HRESULT hr;
  288.     //Use this flag to switch between single thread and apartment model threading
  289.     //        TRUE    => Apartment Model multi-threading
  290.     //        FALSE    => single thread
  291.     BOOL fMarshall = TRUE;
  292.     DAOQueryDef **rgpIqd = NULL;
  293.     DAODBEngine **rgpIdben = NULL;
  294.  
  295.     //How many querydefs are we executing?
  296.     cQd = pView->m_tabQDResults.GetItemCount();
  297.  
  298.     //allocate space for all this
  299.     rgparam = new THREAD_PARAM[cQd];
  300.     rgpIqd = new DAOQueryDef *[cQd];
  301.     rgpIdben = new DAODBEngine *[cQd];
  302.     rghThread = new HANDLE[cQd];
  303.     rgtid = new DWORD[cQd];
  304.  
  305.     //Get the querydefs collection
  306.     if (m_pwksp->GetType() == dbUseJet)
  307.         qds = m_pdb->QueryDefs;
  308.     else
  309.         qds = m_pdb->GetConnection().QueryDefs;
  310.  
  311.     //Walk through each tab to get the QueryDef name
  312.     for (iQd = 0; iQd < cQd; iQd++)
  313.     {
  314.         rgpIqd[iQd] = NULL;
  315.         rgpIdben[iQd] = NULL;
  316.         item.mask = TCIF_TEXT;
  317.         item.pszText = new TCHAR[CBMAXNAME];
  318.         item.cchTextMax;
  319.         pView->m_tabQDResults.GetItem(iQd, &item);
  320.         rgparam[iQd].fMarshall = fMarshall;
  321.         rgparam[iQd].pgrid = &(pView->m_tabQDResults.m_rggridResults[iQd]);
  322.         if (fMarshall)
  323.         {
  324.             rgparam[iQd].pqd = NULL;
  325.             rgpIqd[iQd] = (DAOQueryDef *) qds[item.pszText].GetInterface(TRUE);
  326.             CoMarshalInterThreadInterfaceInStream(IID_IDAOQueryDefW, (LPUNKNOWN) rgpIqd[iQd], &rgparam[iQd].pstmQD);
  327.             rgparam[iQd].pdben = NULL;
  328.             rgpIdben[iQd] = (DAODBEngine *) m_pdben->GetInterface(TRUE);
  329.             CoMarshalInterThreadInterfaceInStream(IID_IDAODBEngineW, (LPUNKNOWN) rgpIdben[iQd], &rgparam[iQd].pstmDBEN);
  330.             rghThread[iQd] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &ExecuteQueryDef, (VOID *) &rgparam[iQd], 0, &rgtid[iQd]);
  331.         }
  332.         else
  333.         {
  334.             rgparam[iQd].pstmQD = NULL;
  335.             rgparam[iQd].pqd = new CdbQueryDef;
  336.             *(rgparam[iQd].pqd) = qds[item.pszText];
  337.             rgparam[iQd].pstmDBEN = NULL;
  338.             rgparam[iQd].pdben = m_pdben;
  339.             ExecuteQueryDef((VOID *) &rgparam[iQd]);
  340.         }
  341.         delete[] item.pszText;
  342.     }
  343.  
  344.     //If this is marshalling, then sit in a message loop
  345.     if (fMarshall)
  346.     {
  347.         fActive = TRUE;
  348.         while (fActive)
  349.         {
  350.             fActive = FALSE;
  351.             for (iQd = 0; iQd < cQd; iQd++)
  352.             {
  353.                 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  354.                 {
  355.                     TranslateMessage(&msg);
  356.                     DispatchMessage(&msg);
  357.                 }
  358.                 GetExitCodeThread(rghThread[iQd], &dwExitCode);
  359.                 if (dwExitCode == STILL_ACTIVE)
  360.                     fActive = TRUE;
  361.                 else
  362.                     rghThread[iQd] = NULL;
  363.             }
  364.         }
  365.     }
  366.  
  367.     //Free allocated memory
  368.     for (iQd = 0; iQd < cQd; iQd++)
  369.     {
  370.         if (rgpIqd[iQd])
  371.             rgpIqd[iQd]->Release();
  372.         if (rgpIdben[iQd])
  373.             rgpIdben[iQd]->Release();
  374.         if (rgparam[iQd].pqd)
  375.             delete rgparam[iQd].pqd;
  376.     }
  377.     if (rgparam)
  378.         delete[] rgparam;
  379.     if (rgpIqd)
  380.         delete[] rgpIqd;
  381.     if (rgpIdben)
  382.         delete[] rgpIdben;
  383.     if (rghThread)
  384.         delete[] rghThread;
  385.     if (rgtid)
  386.         delete[] rgtid;
  387. }
  388.  
  389. void ExecuteQueryDef(VOID *pv)
  390. {
  391.     THREAD_PARAM *pparam = (THREAD_PARAM *)pv;
  392.     CString st;
  393.     CdbField fld;
  394.     CdbRecordset rs;
  395.     CdbQueryDef qd;
  396.     CdbDBEngine dben;
  397.     COleVariant vDataChunk, vData;
  398.     int iFld, cFld, iRow, cRow;
  399.     long rgiData[2];
  400.     DAOQueryDef *pIqd;
  401.     DAODBEngine *pIdben;
  402.     CSize sizeText, sizeCol;
  403.  
  404.     if (pparam->fMarshall)
  405.     {
  406.         CoInitialize(NULL);
  407.         
  408.         CoGetInterfaceAndReleaseStream(pparam->pstmQD, IID_IDAOQueryDefW, (VOID **) &pIqd);
  409.         qd.SetInterface(pIqd);
  410.         CoGetInterfaceAndReleaseStream(pparam->pstmDBEN, IID_IDAODBEngineW, (VOID **) &pIdben);
  411.         dben.SetInterface(pIdben);
  412.     }
  413.     else
  414.     {
  415.         qd = *(pparam->pqd);
  416.         dben = *(pparam->pdben);
  417.     }
  418.  
  419.     st.Format(_T("Executing %s\n"), qd.GetName());
  420.     TRACE(st);
  421.  
  422.     try
  423.     {
  424.         rs = qd.OpenRecordset(dbOpenSnapshot);
  425.         //First, list the field names in the grid
  426.         pparam->pgrid->SetFixedRows(1);
  427.         pparam->pgrid->SetFixedCols(0);
  428.         pparam->pgrid->SetRows(1);
  429.         pparam->pgrid->SetCols(cFld = rs.Fields.GetCount());
  430.         pparam->pgrid->SetRow(0);
  431.         for (iFld = 0; iFld < cFld; iFld++)
  432.         {
  433.             pparam->pgrid->SetCol(iFld);
  434.             pparam->pgrid->SetText(rs.Fields[(long) iFld].GetName());
  435.         }
  436.  
  437.         //Now, get the data
  438.         vDataChunk = rs.GetRows(CMAXRECORDS);
  439.         
  440.         //Finally, fill in the grid with the data
  441.         cRow = vDataChunk.parray->rgsabound[0].cElements;
  442.         pparam->pgrid->SetRows(cRow + 1);
  443.         pparam->pgrid->SetFixedRows(1);
  444.         for (iRow = 0; iRow < cRow; iRow++)
  445.         {
  446.             rgiData[1] = iRow;
  447.             pparam->pgrid->SetRow(iRow + 1);
  448.             for (iFld = 0; iFld < cFld; iFld++)
  449.             {
  450.                 rgiData[0] = iFld;
  451.                 pparam->pgrid->SetCol(iFld);
  452.                 SafeArrayGetElement(vDataChunk.parray, rgiData, (LPVOID)&vData);
  453.                 if (vData.vt == VT_NULL)
  454.                     pparam->pgrid->SetText(_T("#NULL#"));
  455.                 else if (vData.vt == (VT_ARRAY | VT_UI1))
  456.                     pparam->pgrid->SetText(_T("#IMAGE#"));
  457.                 else if (vData.vt == VT_ERROR)
  458.                 {
  459.                     st.Format(_T("Error: 0x%x"), vData.scode);
  460.                     pparam->pgrid->SetText(st);
  461.                 }
  462.                 else
  463.                 {
  464.                     vData.ChangeType(VT_BSTR);
  465.                     pparam->pgrid->SetText(vData.bstrVal);
  466.                 }
  467.             }
  468.         }
  469.     }
  470.     catch (CdbException)
  471.     {
  472.         CString stError;
  473.  
  474.         pparam->pgrid->SetRows(2);
  475.         pparam->pgrid->SetCols(2);
  476.         pparam->pgrid->SetFixedRows(1);
  477.         pparam->pgrid->SetFixedCols(1);
  478.         pparam->pgrid->SetRow(0);
  479.         pparam->pgrid->SetCol(0);
  480.         stError.Format(_T("ERROR: %s"), dben.Errors[0L].GetDescription());
  481.         pparam->pgrid->SetText(stError);
  482.     }
  483.  
  484.     pparam->pgrid->SetCol(0);
  485.     pparam->pgrid->SetRow(1);
  486.  
  487.     if (pparam->fMarshall)
  488.     {
  489.         CoUninitialize();
  490.     }
  491. }
  492.