📄 coledb.cpp
字号:
#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 + -