home *** CD-ROM | disk | FTP | other *** search
- // qdDoc.cpp : implementation of the CQdDoc class
- //
-
- #include "stdafx.h"
- #include "MultThrd.h"
-
- #include "qdDoc.h"
- #include "qdView.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- void ExecuteQueryDef(VOID *pv);
-
- typedef struct _THREADPARAM
- {
- BOOL fMarshall; //TRUE -> pstm is valid, FALSE -> pqd is valid
- LPSTREAM pstmQD;
- CdbQueryDef *pqd;
- LPSTREAM pstmDBEN;
- CdbDBEngine *pdben;
- CGridCtrl *pgrid;
- } THREAD_PARAM;
-
- /////////////////////////////////////////////////////////////////////////////
- // CQdDoc
-
- IMPLEMENT_DYNCREATE(CQdDoc, CDocument)
-
- BEGIN_MESSAGE_MAP(CQdDoc, CDocument)
- //{{AFX_MSG_MAP(CQdDoc)
- ON_COMMAND(ID_FILE_OPENJET, OnFileOpenJet)
- ON_COMMAND(ID_FILE_OPENODBC, OnFileOpenODBC)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // CQdDoc construction/destruction
-
- CQdDoc::CQdDoc()
- {
- m_pdb = NULL;
- m_pwksp = NULL;
- m_pdben = NULL;
- }
-
- CQdDoc::~CQdDoc()
- {
- //If a Database already exists, close it down
- if (m_pdb)
- {
- m_pdb->Close();
- delete m_pdb;
- m_pdb = NULL;
- }
-
- //If a Workspace is open, close it down
- if (m_pwksp)
- {
- m_pwksp->Close();
- delete m_pwksp;
- m_pwksp = NULL;
- }
-
- if (m_pdben)
- delete m_pdben;
- }
-
- BOOL CQdDoc::OnNewDocument()
- {
- if (!CDocument::OnNewDocument())
- return FALSE;
-
- // TODO: add reinitialization code here
- // (SDI documents will reuse this document)
-
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CQdDoc serialization
-
- void CQdDoc::Serialize(CArchive& ar)
- {
- if (ar.IsStoring())
- {
- // TODO: add storing code here
- }
- else
- {
- // TODO: add loading code here
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CQdDoc diagnostics
-
- #ifdef _DEBUG
- void CQdDoc::AssertValid() const
- {
- CDocument::AssertValid();
- }
-
- void CQdDoc::Dump(CDumpContext& dc) const
- {
- CDocument::Dump(dc);
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // CQdDoc commands
-
- void CQdDoc::OnFileOpenJet()
- {
- static TCHAR BASED_CODE szFilter[] = _T("Jet DBs (*.mdb)|*.mdb|All Files (*.*)|*.*||");
- CFileDialog dlgFile(TRUE, _T("MDB"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
- long lType;
- CString stDB;
-
- if (dlgFile.DoModal() == IDCANCEL)
- return;
- stDB = dlgFile.GetPathName();
-
- //If a Database already exists, close it down
- if (m_pdb)
- {
- m_pdb->Close();
- delete m_pdb;
- m_pdb = NULL;
- }
-
- //A workspace may already exist. If so, check the
- // type. If the type is not Jet, close it down and recreate a Jet
- // workspace. If it is Jet, then cool.
- if (m_pwksp)
- {
- lType = m_pwksp->GetType();
- if (lType != dbUseJet)
- {
- m_pwksp->Close();
- delete m_pwksp;
- m_pwksp = NULL;
- }
- }
-
- //Start DAO if its not already started
- if (m_pdben == NULL)
- m_pdben = new CdbDBEngine;
-
- //Create a Jet workspace if one is not already active
- if (m_pwksp == NULL)
- {
- m_pwksp = new CdbWorkspace;
- *m_pwksp = m_pdben->CreateWorkspace(_T("wsJet"), _T("admin"), _T(""), dbUseJet);
- }
-
- //Open the database
- m_pdb = new CdbDatabase();
- try
- {
- *m_pdb = m_pwksp->OpenDatabase(stDB);
-
- TRACE(_T("Opened Database : %s\n"), m_pdb->GetName());
- UpdateAllViews(NULL, UPDATEHINT_NEWDATABASE, m_pdb);
- }
- catch (CdbException)
- {
- CString stError;
- stError.Format(_T("ERROR: %s"), m_pdben->Errors[0L].GetDescription());
- AfxMessageBox(stError);
- delete m_pdb;
- m_pdb = NULL;
- }
- }
-
- void CQdDoc::OnFileOpenODBC()
- {
- long lType;
-
- //If a Database already exists, close it down
- if (m_pdb)
- {
- m_pdb->Close();
- delete m_pdb;
- m_pdb = NULL;
- }
-
- //A workspace may already exist. If so, check the
- // type. If the type is not ODBC, close it down and recreate an ODBC
- // workspace. If it is ODBC, then cool.
- if (m_pwksp)
- {
- lType = m_pwksp->GetType();
- if (lType != dbUseODBC)
- {
- m_pwksp->Close();
- delete m_pwksp;
- m_pwksp = NULL;
- }
- }
-
- //Start DAO if its not already started
- if (m_pdben == NULL)
- m_pdben = new CdbDBEngine;
-
- //Create an ODBC workspace if one is not already active
- if (m_pwksp == NULL)
- {
- m_pwksp = new CdbWorkspace;
- *m_pwksp = m_pdben->CreateWorkspace(_T("wsJet"), _T("admin"), _T(""), dbUseODBC);
- }
-
- //Open the database
- m_pdb = new CdbDatabase();
- try
- {
- *m_pdb = m_pwksp->OpenDatabase(_T(""));
-
- TRACE(_T("Opened Database : %s\n"), m_pdb->GetName());
- UpdateAllViews(NULL, UPDATEHINT_NEWDATABASE, m_pdb);
- }
- catch (CdbException e)
- {
- //Only notify the user if they didn't explicitly cancel the open
- if (e.m_hr != E_DAO_OperationCanceled)
- {
- CString stError;
- stError.Format(_T("ERROR: %s"), m_pdben->Errors[0L].GetDescription());
- AfxMessageBox(stError);
- }
-
- //Kill the new database object
- delete m_pdb;
- m_pdb = NULL;
- }
- }
-
- BOOL CQdDoc::CreateNewQD(CString &stName, CString &stSQL)
- {
- BOOL fPassed = TRUE;
- CdbQueryDef qd;
- CdbConnection cn;
-
- try
- {
- if (m_pwksp->GetType() == dbUseJet)
- qd = m_pdb->CreateQueryDef(stName, stSQL);
- else
- {
- cn = m_pdb->GetConnection();
- qd = cn.CreateQueryDef(stName, stSQL);
- }
- m_stNewQueryDef = stName;
- UpdateAllViews(NULL, UPDATEHINT_NEWQUERYDEF, m_pdb);
- }
- catch (CdbException)
- {
- CString stError;
- int cErr;
-
- cErr = m_pdben->Errors.GetCount();
- stError.Format(_T("Failed to create new querydef: '%s'"), m_pdben->Errors[(long) (cErr - 1)].GetDescription());
- AfxMessageBox(stError);
- fPassed = FALSE;
- }
-
- return fPassed;
- }
-
- void CQdDoc::ExecuteQDs()
- {
- POSITION pos = GetFirstViewPosition();
- CQdView* pView = (CQdView *) GetNextView(pos);
- int cQd, iQd;
- TC_ITEM item;
- CdbQueryDefs qds;
- CdbQueryDef qd;
- THREAD_PARAM *rgparam = NULL;
- HANDLE *rghThread = NULL;
- DWORD *rgtid = NULL;
- DWORD dwExitCode;
- BOOL fActive;
- MSG msg;
- HRESULT hr;
- //Use this flag to switch between single thread and apartment model threading
- // TRUE => Apartment Model multi-threading
- // FALSE => single thread
- BOOL fMarshall = TRUE;
- DAOQueryDef **rgpIqd = NULL;
- DAODBEngine **rgpIdben = NULL;
-
- //How many querydefs are we executing?
- cQd = pView->m_tabQDResults.GetItemCount();
-
- //allocate space for all this
- rgparam = new THREAD_PARAM[cQd];
- rgpIqd = new DAOQueryDef *[cQd];
- rgpIdben = new DAODBEngine *[cQd];
- rghThread = new HANDLE[cQd];
- rgtid = new DWORD[cQd];
-
- //Get the querydefs collection
- if (m_pwksp->GetType() == dbUseJet)
- qds = m_pdb->QueryDefs;
- else
- qds = m_pdb->GetConnection().QueryDefs;
-
- //Walk through each tab to get the QueryDef name
- for (iQd = 0; iQd < cQd; iQd++)
- {
- rgpIqd[iQd] = NULL;
- rgpIdben[iQd] = NULL;
- item.mask = TCIF_TEXT;
- item.pszText = new TCHAR[CBMAXNAME];
- item.cchTextMax;
- pView->m_tabQDResults.GetItem(iQd, &item);
- rgparam[iQd].fMarshall = fMarshall;
- rgparam[iQd].pgrid = &(pView->m_tabQDResults.m_rggridResults[iQd]);
- if (fMarshall)
- {
- rgparam[iQd].pqd = NULL;
- rgpIqd[iQd] = (DAOQueryDef *) qds[item.pszText].GetInterface(TRUE);
- CoMarshalInterThreadInterfaceInStream(IID_IDAOQueryDefW, (LPUNKNOWN) rgpIqd[iQd], &rgparam[iQd].pstmQD);
- rgparam[iQd].pdben = NULL;
- rgpIdben[iQd] = (DAODBEngine *) m_pdben->GetInterface(TRUE);
- CoMarshalInterThreadInterfaceInStream(IID_IDAODBEngineW, (LPUNKNOWN) rgpIdben[iQd], &rgparam[iQd].pstmDBEN);
- rghThread[iQd] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &ExecuteQueryDef, (VOID *) &rgparam[iQd], 0, &rgtid[iQd]);
- }
- else
- {
- rgparam[iQd].pstmQD = NULL;
- rgparam[iQd].pqd = new CdbQueryDef;
- *(rgparam[iQd].pqd) = qds[item.pszText];
- rgparam[iQd].pstmDBEN = NULL;
- rgparam[iQd].pdben = m_pdben;
- ExecuteQueryDef((VOID *) &rgparam[iQd]);
- }
- delete[] item.pszText;
- }
-
- //If this is marshalling, then sit in a message loop
- if (fMarshall)
- {
- fActive = TRUE;
- while (fActive)
- {
- fActive = FALSE;
- for (iQd = 0; iQd < cQd; iQd++)
- {
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- GetExitCodeThread(rghThread[iQd], &dwExitCode);
- if (dwExitCode == STILL_ACTIVE)
- fActive = TRUE;
- else
- rghThread[iQd] = NULL;
- }
- }
- }
-
- //Free allocated memory
- for (iQd = 0; iQd < cQd; iQd++)
- {
- if (rgpIqd[iQd])
- rgpIqd[iQd]->Release();
- if (rgpIdben[iQd])
- rgpIdben[iQd]->Release();
- if (rgparam[iQd].pqd)
- delete rgparam[iQd].pqd;
- }
- if (rgparam)
- delete[] rgparam;
- if (rgpIqd)
- delete[] rgpIqd;
- if (rgpIdben)
- delete[] rgpIdben;
- if (rghThread)
- delete[] rghThread;
- if (rgtid)
- delete[] rgtid;
- }
-
- void ExecuteQueryDef(VOID *pv)
- {
- THREAD_PARAM *pparam = (THREAD_PARAM *)pv;
- CString st;
- CdbField fld;
- CdbRecordset rs;
- CdbQueryDef qd;
- CdbDBEngine dben;
- COleVariant vDataChunk, vData;
- int iFld, cFld, iRow, cRow;
- long rgiData[2];
- DAOQueryDef *pIqd;
- DAODBEngine *pIdben;
- CSize sizeText, sizeCol;
-
- if (pparam->fMarshall)
- {
- CoInitialize(NULL);
-
- CoGetInterfaceAndReleaseStream(pparam->pstmQD, IID_IDAOQueryDefW, (VOID **) &pIqd);
- qd.SetInterface(pIqd);
- CoGetInterfaceAndReleaseStream(pparam->pstmDBEN, IID_IDAODBEngineW, (VOID **) &pIdben);
- dben.SetInterface(pIdben);
- }
- else
- {
- qd = *(pparam->pqd);
- dben = *(pparam->pdben);
- }
-
- st.Format(_T("Executing %s\n"), qd.GetName());
- TRACE(st);
-
- try
- {
- rs = qd.OpenRecordset(dbOpenSnapshot);
- //First, list the field names in the grid
- pparam->pgrid->SetFixedRows(1);
- pparam->pgrid->SetFixedCols(0);
- pparam->pgrid->SetRows(1);
- pparam->pgrid->SetCols(cFld = rs.Fields.GetCount());
- pparam->pgrid->SetRow(0);
- for (iFld = 0; iFld < cFld; iFld++)
- {
- pparam->pgrid->SetCol(iFld);
- pparam->pgrid->SetText(rs.Fields[(long) iFld].GetName());
- }
-
- //Now, get the data
- vDataChunk = rs.GetRows(CMAXRECORDS);
-
- //Finally, fill in the grid with the data
- cRow = vDataChunk.parray->rgsabound[0].cElements;
- pparam->pgrid->SetRows(cRow + 1);
- pparam->pgrid->SetFixedRows(1);
- for (iRow = 0; iRow < cRow; iRow++)
- {
- rgiData[1] = iRow;
- pparam->pgrid->SetRow(iRow + 1);
- for (iFld = 0; iFld < cFld; iFld++)
- {
- rgiData[0] = iFld;
- pparam->pgrid->SetCol(iFld);
- SafeArrayGetElement(vDataChunk.parray, rgiData, (LPVOID)&vData);
- if (vData.vt == VT_NULL)
- pparam->pgrid->SetText(_T("#NULL#"));
- else if (vData.vt == (VT_ARRAY | VT_UI1))
- pparam->pgrid->SetText(_T("#IMAGE#"));
- else if (vData.vt == VT_ERROR)
- {
- st.Format(_T("Error: 0x%x"), vData.scode);
- pparam->pgrid->SetText(st);
- }
- else
- {
- vData.ChangeType(VT_BSTR);
- pparam->pgrid->SetText(vData.bstrVal);
- }
- }
- }
- }
- catch (CdbException)
- {
- CString stError;
-
- pparam->pgrid->SetRows(2);
- pparam->pgrid->SetCols(2);
- pparam->pgrid->SetFixedRows(1);
- pparam->pgrid->SetFixedCols(1);
- pparam->pgrid->SetRow(0);
- pparam->pgrid->SetCol(0);
- stError.Format(_T("ERROR: %s"), dben.Errors[0L].GetDescription());
- pparam->pgrid->SetText(stError);
- }
-
- pparam->pgrid->SetCol(0);
- pparam->pgrid->SetRow(1);
-
- if (pparam->fMarshall)
- {
- CoUninitialize();
- }
- }
-