⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 coledb.cpp

📁 remote debug and compile tools
💻 CPP
📖 第 1 页 / 共 3 页
字号:

#include "stdafx.h"
#include "cOledb.h"


//////////////////////////////////////////////////////////////
// COledbSystem
//

COledbSystem::COledbSystem()
{
}

COledbSystem::~COledbSystem()
{
}

BOOL COledbSystem::Initialize()
{
   ::CoInitialize(NULL);
   return TRUE;
}

void COledbSystem::Terminate()
{
   ::CoUninitialize();
}

CDbDatabase* COledbSystem::CreateDatabase()
{
   return new COledbDatabase(this);
}

CDbRecordset* COledbSystem::CreateRecordset(CDbDatabase* pDb)
{
   return new COledbRecordset(static_cast<COledbDatabase*>(pDb));
}

CDbCommand* COledbSystem::CreateCommand(CDbDatabase* pDb)
{
   return new COledbCommand(static_cast<COledbDatabase*>(pDb));
}


//////////////////////////////////////////////////////////////
// COledbDatabase
//

COledbDatabase::COledbDatabase(COledbSystem* pSystem) : 
   m_pSystem(pSystem)
{
   _ASSERTE(pSystem);
   ATLTRY(m_pErrors = new COledbErrors);
#ifdef _DEBUG
   m_nRecordsets = 0;
#endif
}

COledbDatabase::~COledbDatabase()
{
   Close();
   delete m_pErrors;
#ifdef _DEBUG
   // Check that all recordsets have been closed and deleted
   _ASSERTE(m_nRecordsets==0);
#endif
}

BOOL COledbDatabase::Open(HWND hWnd, LPCTSTR pstrConnectionString, LPCTSTR pstrUser, LPCTSTR pstrPassword, long iType)
{
   HRESULT Hr;

   Close();

   if( (iType & DB_OPEN_PROMPTDIALOG) != 0 ) 
   {
      // Initialize from Data Links UI

      CComPtr<IDBPromptInitialize> spPrompt;
      Hr = spPrompt.CoCreateInstance(CLSID_DataLinks);
      if( FAILED(Hr) ) return FALSE;

      if( hWnd == NULL ) hWnd = ::GetActiveWindow();
      if( hWnd == NULL ) hWnd = ::GetDesktopWindow();

      Hr = spPrompt->PromptDataSource(
         NULL,                             // pUnkOuter
         hWnd,                             // hWndParent
         DBPROMPTOPTIONS_PROPERTYSHEET,    // dwPromptOptions
         0,                                // cSourceTypeFilter
         NULL,                             // rgSourceTypeFilter
         NULL,                             // pwszszzProviderFilter
         IID_IDBInitialize,                // riid
         (LPUNKNOWN*) &m_spInit);          // ppDataSource
      if( Hr == S_FALSE ) Hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_CANCELLED);  // The user clicked cancel
      if( FAILED(Hr) ) return FALSE;
   }
   else 
   {
      TCHAR szPrefix[10] = { 0 };
      ::lstrcpyn(szPrefix, pstrConnectionString, (sizeof(szPrefix) / sizeof(TCHAR)) - 1);
      if( ::lstrcmpi(szPrefix, _T("Provider=")) == 0 ) 
      {
         // Connect using OLE DB connection string

         CComPtr<IDataInitialize> spDataInit;
         Hr = spDataInit.CoCreateInstance(CLSID_MSDAINITIALIZE);
         if( FAILED(Hr) ) return Hr;

         USES_CONVERSION;
         Hr = spDataInit->GetDataSource(NULL, CLSCTX_INPROC_SERVER, T2OLE((LPTSTR)pstrConnectionString), IID_IDBInitialize, (LPUNKNOWN*)&m_spInit);
         if( FAILED(Hr) ) return Hr;
      }
      else 
      {
         // Initialize from ODBC DSN information

         Hr = m_spInit.CoCreateInstance(L"MSDASQL");
         if( FAILED(Hr) ) return FALSE;

         DBPROPSET PropSet;
         const ULONG nMaxProps = 4;
         DBPROP Prop[nMaxProps];
         ULONG iProp = 0;

         // Initialize common property options.
         ULONG i;
         for( i = 0; i < nMaxProps; i++ ) {
            ::VariantInit(&Prop[i].vValue);
            Prop[i].dwOptions = DBPROPOPTIONS_REQUIRED;
            Prop[i].colid = DB_NULLID;
         }

         // Level of prompting that will be done to complete the connection process
         Prop[iProp].dwPropertyID = DBPROP_INIT_PROMPT;
         Prop[iProp].vValue.vt = VT_I2;
         Prop[iProp].vValue.iVal = DBPROMPT_NOPROMPT;    
         iProp++;
         // Data source name--see the sample source included with the OLE DB SDK.
         Prop[iProp].dwPropertyID = DBPROP_INIT_DATASOURCE;   
         Prop[iProp].vValue.vt = VT_BSTR;
         Prop[iProp].vValue.bstrVal = T2BSTR(pstrConnectionString);
         iProp++;
         if( pstrUser ) {
            // User ID
            Prop[iProp].dwPropertyID = DBPROP_AUTH_USERID;
            Prop[iProp].vValue.vt = VT_BSTR;
            Prop[iProp].vValue.bstrVal = T2BSTR(pstrUser);
            iProp++;
         }
         if( pstrPassword ) {
            // Password
            Prop[iProp].dwPropertyID = DBPROP_AUTH_PASSWORD;
            Prop[iProp].vValue.vt = VT_BSTR;
            Prop[iProp].vValue.bstrVal = T2BSTR(pstrPassword);
            iProp++;
         }

         // Prepare properties
         PropSet.guidPropertySet = DBPROPSET_DBINIT;
         PropSet.cProperties = iProp;
         PropSet.rgProperties = Prop;
         // Set initialization properties.
         CComQIPtr<IDBProperties> spProperties = m_spInit;
         Hr = spProperties->SetProperties(1, &PropSet);
      
         // Before we check if it failed, clean up
         for( i = 0; i < nMaxProps; i++ ) ::VariantClear(&Prop[i].vValue);
      
         // Did SetProperties() fail?
         if( FAILED(Hr) ) return FALSE;
      }

   }

   return Connect();
}

BOOL COledbDatabase::Connect()
{
   _ASSERTE(m_spInit);
   if( m_spInit == NULL ) return FALSE;

   // Initialize datasource
   HRESULT Hr = m_spInit->Initialize();
   if( FAILED(Hr) ) return _Error(Hr);

   // Create session
   CComQIPtr<IDBCreateSession> spCreateSession = m_spInit;
   if( spCreateSession == NULL ) return FALSE;
   Hr = spCreateSession->CreateSession(NULL, IID_IOpenRowset, (LPUNKNOWN*) &m_spSession);
   if( FAILED(Hr) ) return _Error(Hr);

   return TRUE;
}

void COledbDatabase::Close()
{
   m_spSession.Release();
   if( m_spInit ) {
      m_spInit->Uninitialize();
      m_spInit.Release();
   }
}

BOOL COledbDatabase::IsOpen() const
{
   return m_spSession != NULL;
}

BOOL COledbDatabase::ExecuteSQL(LPCTSTR pstrSQL, long lType /*= DB_OPEN_TYPE_FORWARD_ONLY*/, long lOptions /*= DB_OPTION_DEFAULT*/, DWORD* pdwRowsAffected/*= NULL*/)
{
   USES_CONVERSION;
   HRESULT Hr;

   if( pdwRowsAffected ) *pdwRowsAffected = 0;
   CComQIPtr<IDBCreateCommand> spCreate = m_spSession;
   if( spCreate == NULL ) return FALSE;
   CComPtr<ICommand> spCommand;
   Hr = spCreate->CreateCommand(NULL, IID_ICommand, (LPUNKNOWN*) &spCommand);
   if( FAILED(Hr) ) return _Error(Hr);
   _SetRecordsetType(spCommand, lType, lOptions);
   CComQIPtr<ICommandText> spText = spCommand;
   _ASSERTE(spText);
   Hr = spText->SetCommandText(DBGUID_DBSQL, T2CW(pstrSQL));
   if( FAILED(Hr) ) return _Error(Hr);
   CComPtr<IRowset> spRowset;
   Hr = spText->Execute(NULL, IID_IRowset, NULL, (LONG*) pdwRowsAffected, (LPUNKNOWN*) &spRowset);
   if( FAILED(Hr) ) return _Error(Hr);
   return TRUE;
}

BOOL COledbDatabase::BeginTrans()
{
   return BeginTrans(ISOLATIONLEVEL_READCOMMITTED);
}

BOOL COledbDatabase::BeginTrans(ISOLEVEL isoLevel)
{
   CComQIPtr<ITransactionLocal> spTransaction = m_spSession;
   if( spTransaction == NULL ) return FALSE;
   HRESULT Hr = spTransaction->StartTransaction(isoLevel, 0, NULL, NULL);
   return SUCCEEDED(Hr) ? TRUE : _Error(Hr);
}

BOOL COledbDatabase::CommitTrans()
{
   CComQIPtr<ITransaction> spTransaction = m_spSession;
   if( spTransaction == NULL ) return FALSE;
   BOOL bRetaining = FALSE;
   DWORD grfTC = XACTTC_SYNC;
   DWORD grfRM = 0;
   HRESULT Hr = spTransaction->Commit(bRetaining, grfTC, grfRM);
   _ASSERTE(SUCCEEDED(Hr));
   return SUCCEEDED(Hr) ? TRUE : _Error(Hr);
}

BOOL COledbDatabase::RollbackTrans()
{
   CComQIPtr<ITransaction> spTransaction = m_spSession;
   if( spTransaction == NULL ) return FALSE;
   BOID* pboidReason = NULL;
   BOOL bRetaining = FALSE;
   BOOL bAsync = FALSE;
   HRESULT Hr = spTransaction->Abort(pboidReason, bRetaining, bAsync);
   _ASSERTE(SUCCEEDED(Hr));
   return SUCCEEDED(Hr) ? TRUE : _Error(Hr);
}

void COledbDatabase::SetLoginTimeout(long lTimeout)
{
   m_lLoginTimeout = lTimeout;
}

void COledbDatabase::SetQueryTimeout(long lTimeout)
{
   m_lQueryTimeout = lTimeout;
}

CDbErrors* COledbDatabase::GetErrors()
{
   _ASSERTE(m_pErrors);
   return m_pErrors;
}

BOOL COledbDatabase::_Error(HRESULT Hr)
{
   _ASSERTE(m_pErrors);
   m_pErrors->_Init(Hr);
   return FALSE; // Always return FALSE to allow "return _Error();" constructs...  
}

void COledbDatabase::_SetRecordsetType(ICommand* pCommand, long lType, long /*lOptions*/)
{
   DBPROPSET PropSet;
   const ULONG nMaxProps = 8;
   DBPROP Prop[nMaxProps];
   ULONG iProp = 0;

   // Initialize common property options.
   ULONG i;
   for( i = 0; i < nMaxProps; i++ ) {
      ::VariantInit(&Prop[i].vValue);
      Prop[i].dwOptions = DBPROPOPTIONS_REQUIRED;
      Prop[i].colid = DB_NULLID;
      Prop[1].dwStatus = 0;
   }

   if( lType == DB_OPEN_TYPE_FORWARD_ONLY ) {
      // None
   }
   else if( lType == DB_OPEN_TYPE_SNAPSHOT ) {
      Prop[iProp].dwPropertyID = DBPROP_CANFETCHBACKWARDS;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
      Prop[iProp].dwPropertyID = DBPROP_CANSCROLLBACKWARDS;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
/*
      Prop[iProp].dwPropertyID = DBPROP_CANHOLDROWS;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
*/
   }
   else if( lType == DB_OPEN_TYPE_DYNASET ) {
      Prop[iProp].dwPropertyID = DBPROP_BOOKMARKS;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_FALSE;
      iProp++;
      Prop[iProp].dwPropertyID = DBPROP_CANFETCHBACKWARDS;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
      Prop[iProp].dwPropertyID = DBPROP_CANSCROLLBACKWARDS;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
      Prop[iProp].dwPropertyID = DBPROP_OTHERINSERT;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
      Prop[iProp].dwPropertyID = DBPROP_OTHERUPDATEDELETE;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
      Prop[iProp].dwPropertyID = DBPROP_REMOVEDELETED;
      Prop[iProp].vValue.vt = VT_BOOL;
      Prop[iProp].vValue.boolVal = VARIANT_TRUE;
      iProp++;
   }
   else {
      _ASSERTE(false);
   }

   // Prepare properties
   PropSet.guidPropertySet = DBPROPSET_ROWSET;
   PropSet.cProperties = iProp;
   PropSet.rgProperties = Prop;
   // Set initialization properties.
   CComQIPtr<ICommandProperties> spProperties = pCommand;
   if( iProp > 0 ) {
      HRESULT Hr = spProperties->SetProperties(1, &PropSet);
      _ASSERTE(SUCCEEDED(Hr));
      Hr;
   }

   // Clean up
   for( i = 0; i < nMaxProps; i++ ) ::VariantClear(&Prop[i].vValue);
}

//////////////////////////////////////////////////////////////
// COledbRecordset
//

COledbRecordset::COledbRecordset(COledbDatabase* pDb) : 
   m_pDb(pDb), 
   m_pData(NULL),
   m_rgBindings(NULL),
   m_hAccessor(DB_NULL_HACCESSOR), 
   m_pwstrNameBuffer(NULL),
   m_fEOF(true)
{
   _ASSERTE(m_pDb==NULL || m_pDb->IsOpen());
#ifdef _DEBUG
   if( m_pDb ) m_pDb->m_nRecordsets++;
#endif
}

COledbRecordset::COledbRecordset(IRowset* pRS) : 
   m_pDb(NULL), 
   m_pData(NULL),
   m_rgBindings(NULL), 
   m_hAccessor(DB_NULL_HACCESSOR), 
   m_pwstrNameBuffer(NULL),
   m_fEOF(true)
{
   Attach(pRS);
}

COledbRecordset::~COledbRecordset()
{
   _ASSERTE(m_pDb==NULL || m_pDb->IsOpen());
   Close();
#ifdef _DEBUG
   if( m_pDb ) m_pDb->m_nRecordsets--;
#endif
}

BOOL COledbRecordset::Open(LPCTSTR pstrSQL, long lType /*= DB_OPEN_TYPE_FORWARD_ONLY*/, long lOptions /*= DB_OPTION_DEFAULT*/)
{
   _ASSERTE(m_pDb==NULL || m_pDb->IsOpen());
   _ASSERTE(!::IsBadStringPtr(pstrSQL,-1));
   HRESULT Hr;

   // Close old recordset
   Close();

   m_nRowsAffected = 0;

   // Create a new recordset
   CComQIPtr<IDBCreateCommand> spCreate = m_pDb->m_spSession;
   if( spCreate == NULL ) return FALSE;
   CComPtr<ICommand> spCommand;
   Hr = spCreate->CreateCommand(NULL, IID_ICommand, (LPUNKNOWN*) &spCommand);
   if( FAILED(Hr) ) return _Error(Hr);
   // Set type
   COledbDatabase::_SetRecordsetType(spCommand, lType, lOptions);
   // Set SQL
   CComQIPtr<ICommandText> spText = spCommand;
   _ASSERTE(spText);
   USES_CONVERSION;
   Hr = spText->SetCommandText(DBGUID_DBSQL, T2COLE(pstrSQL));
   if( FAILED(Hr) ) return _Error(Hr);

   // Execute...
   Hr = spText->Execute(NULL, IID_IRowset, NULL, &m_nRowsAffected, (LPUNKNOWN*) &m_spRowset);
   if( FAILED(Hr) ) return _Error(Hr);

   // Bind columns
   if( !_BindColumns() ) return FALSE;

   return MoveNext();
}

void COledbRecordset::Close()
{
   if( m_pData ) {
      ::CoTaskMemFree(m_pData);
      m_pData = NULL;
   }
   if( m_rgBindings ) {
      ::CoTaskMemFree(m_rgBindings);
      m_rgBindings = NULL;
   }
   if( m_pwstrNameBuffer ) {
      ::CoTaskMemFree(m_pwstrNameBuffer);
      m_pwstrNameBuffer = NULL;
   }
   m_hAccessor = DB_NULL_HACCESSOR;
   m_nCols = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -