You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
10 KiB
405 lines
10 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
Database.cpp
|
|
|
|
Abstract:
|
|
This file contains the implementation of the JetBlue::Database class.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 05/17/2000
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include <stdafx.h>
|
|
#include <strsafe.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
JetBlue::Database::Database( /*[in]*/ Session* parent ,
|
|
/*[in]*/ JET_SESID sesid ,
|
|
/*[in]*/ LPCSTR szName )
|
|
{
|
|
m_parent = parent; // Session* m_parent;
|
|
m_sesid = sesid; // JET_SESID m_sesid;
|
|
m_dbid = JET_dbidNil; // JET_DBID m_dbid;
|
|
m_strName = szName; // MPC::string m_strName;
|
|
// TableMap m_mapTables;
|
|
}
|
|
|
|
JetBlue::Database::~Database()
|
|
{
|
|
(void)Close( true );
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT JetBlue::Database::Refresh()
|
|
{
|
|
__HCP_FUNC_ENTRY( "JetBlue::Database::Refresh" );
|
|
|
|
HRESULT hr;
|
|
JET_OBJECTLIST info; ::ZeroMemory( &info, sizeof(info) ); info.cbStruct = sizeof(info); info.tableid = JET_tableidNil;
|
|
Table* tblNew = NULL;
|
|
|
|
|
|
m_mapTables.clear();
|
|
|
|
|
|
if(m_dbid != JET_dbidNil)
|
|
{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Read table definition.
|
|
//
|
|
// JET_OBJECTLIST
|
|
// {
|
|
// unsigned long cbStruct;
|
|
// JET_TABLEID tableid;
|
|
// unsigned long cRecord;
|
|
// JET_COLUMNID columnidcontainername;
|
|
// JET_COLUMNID columnidobjectname;
|
|
// JET_COLUMNID columnidobjtyp;
|
|
// JET_COLUMNID columniddtCreate; // XXX -- to be deleted
|
|
// JET_COLUMNID columniddtUpdate; // XXX -- to be deleted
|
|
// JET_COLUMNID columnidgrbit;
|
|
// JET_COLUMNID columnidflags;
|
|
// JET_COLUMNID columnidcRecord; /* Level 2 info */
|
|
// JET_COLUMNID columnidcPage; /* Level 2 info */
|
|
// };
|
|
//
|
|
// JET_RETRIEVECOLUMN
|
|
// {
|
|
// JET_COLUMNID columnid;
|
|
// void *pvData;
|
|
// unsigned long cbData;
|
|
// unsigned long cbActual;
|
|
// JET_GRBIT grbit;
|
|
// unsigned long ibLongValue;
|
|
// unsigned long itagSequence;
|
|
// JET_COLUMNID columnidNextTagged;
|
|
// JET_ERR err;
|
|
// };
|
|
JET_RETRIEVECOLUMN rc [1 ]; ::ZeroMemory( &rc, sizeof(rc) );
|
|
char tblName[JET_cbNameMost+1];
|
|
int i;
|
|
|
|
|
|
__MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetGetObjectInfo( m_sesid, m_dbid, JET_objtypTable, NULL, NULL, &info, sizeof(info), JET_ObjInfoList ));
|
|
|
|
__MPC_JET_INIT_RETRIEVE_COL( rc, 0, info.columnidobjectname, tblName, JET_cbNameMost );
|
|
|
|
|
|
for(i=0; i<info.cRecord; i++)
|
|
{
|
|
::ZeroMemory( tblName, sizeof(tblName) );
|
|
|
|
__MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetMove ( m_sesid, info.tableid, (i == 0 ? JET_MoveFirst : JET_MoveNext), 0 ));
|
|
__MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetRetrieveColumns( m_sesid, info.tableid, rc, ARRAYSIZE(rc) ));
|
|
|
|
__MPC_EXIT_IF_ALLOC_FAILS(hr, tblNew, new Table( m_sesid, m_dbid, tblName ));
|
|
|
|
m_mapTables[tblName] = tblNew; tblNew = NULL;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(info.tableid != JET_tableidNil)
|
|
{
|
|
__MPC_JET__MTSAFE_NORESULT(m_sesid, ::JetCloseTable( m_sesid, info.tableid ));
|
|
}
|
|
|
|
if(tblNew) delete tblNew;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT JetBlue::Database::Open( /*[in]*/ bool fReadOnly ,
|
|
/*[in]*/ bool fCreate ,
|
|
/*[in]*/ bool fRepair )
|
|
{
|
|
__HCP_FUNC_ENTRY( "JetBlue::Database::Open" );
|
|
|
|
HRESULT hr;
|
|
JET_ERR err;
|
|
JET_GRBIT grbit = fReadOnly ? JET_bitDbReadOnly : 0;
|
|
bool fLocked = false;
|
|
|
|
|
|
//
|
|
// In case we cannot lock the database, we try to release it and relock it.
|
|
//
|
|
if(m_parent->LockDatabase( m_strName, fReadOnly ) == false)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Close());
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->ReleaseDatabase( m_strName ));
|
|
|
|
if(m_parent->LockDatabase( m_strName, fReadOnly ) == false)
|
|
{
|
|
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BUSY);
|
|
}
|
|
}
|
|
fLocked = true;
|
|
|
|
|
|
if(m_dbid == JET_dbidNil)
|
|
{
|
|
err = ::JetAttachDatabase( m_sesid, m_strName.c_str(), grbit );
|
|
if(err < JET_errSuccess)
|
|
{
|
|
if(err == JET_errDatabaseCorrupted && fRepair)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Repair());
|
|
|
|
err = ::JetAttachDatabase( m_sesid, m_strName.c_str(), grbit );
|
|
}
|
|
|
|
if(err == JET_errDatabaseCorrupted || fCreate == false)
|
|
{
|
|
__MPC_EXIT_IF_JET_FAILS(hr, err);
|
|
}
|
|
|
|
__MPC_EXIT_IF_JET_FAILS(hr, ::JetCreateDatabase( m_sesid, m_strName.c_str(), NULL, &m_dbid, 0 ));
|
|
}
|
|
else
|
|
{
|
|
__MPC_EXIT_IF_JET_FAILS(hr, ::JetOpenDatabase( m_sesid, m_strName.c_str(), NULL, &m_dbid, 0 ));
|
|
}
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Refresh());
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(FAILED(hr) && fLocked)
|
|
{
|
|
m_parent->UnlockDatabase( m_strName );
|
|
}
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT JetBlue::Database::Close( /*[in]*/ bool fForce, /*[in]*/ bool fAll )
|
|
{
|
|
__HCP_FUNC_ENTRY( "JetBlue::Database::Close" );
|
|
|
|
HRESULT hr;
|
|
JET_ERR err;
|
|
TableIter it;
|
|
|
|
|
|
for(it = m_mapTables.begin(); it != m_mapTables.end(); it++)
|
|
{
|
|
Table* tbl = it->second;
|
|
|
|
if(tbl)
|
|
{
|
|
HRESULT hr2 = tbl->Close( fForce ); if(!fForce) __MPC_EXIT_IF_METHOD_FAILS(hr, hr2);
|
|
|
|
delete tbl;
|
|
}
|
|
}
|
|
m_mapTables.clear();
|
|
|
|
|
|
if(fAll && m_dbid != JET_dbidNil)
|
|
{
|
|
err = ::JetCloseDatabase( m_sesid, m_dbid, 0 ); if(!fForce) __MPC_EXIT_IF_JET_FAILS(hr, err);
|
|
|
|
m_dbid = JET_dbidNil;
|
|
|
|
m_parent->UnlockDatabase( m_strName );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT JetBlue::Database::Delete( /*[in]*/ bool fForce )
|
|
{
|
|
__HCP_FUNC_ENTRY( "JetBlue::Database::Delete" );
|
|
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Close( fForce ));
|
|
|
|
if(m_strName.length() > 0)
|
|
{
|
|
MPC::FileSystemObject fso( A2W( m_strName.c_str() ) );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, fso.Delete( fForce ));
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT JetBlue::Database::GetTable( /*[in] */ LPCSTR szName ,
|
|
/*[out]*/ Table*& tbl ,
|
|
/*[in] */ JET_TABLECREATE* pDef )
|
|
{
|
|
__HCP_FUNC_ENTRY( "JetBlue::Database::GetTable" );
|
|
|
|
HRESULT hr;
|
|
HRESULT hr2;
|
|
Table* tblNew = NULL;
|
|
TableIter it;
|
|
|
|
|
|
__MPC_JET_CHECKHANDLE(hr,m_sesid,JET_sesidNil );
|
|
|
|
|
|
if(pDef) szName = pDef->szTableName;
|
|
|
|
|
|
it = m_mapTables.find( szName );
|
|
if(it == m_mapTables.end())
|
|
{
|
|
__MPC_EXIT_IF_ALLOC_FAILS(hr, tblNew, new Table( m_sesid, m_dbid, szName ));
|
|
|
|
m_mapTables[szName] = tblNew;
|
|
|
|
tbl = tblNew; tblNew = NULL;
|
|
}
|
|
else
|
|
{
|
|
tbl = it->second;
|
|
}
|
|
|
|
if(FAILED(hr2 = tbl->Open()))
|
|
{
|
|
if(pDef == NULL || hr2 != JetERRToHRESULT( JET_errObjectNotFound ))
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, hr2);
|
|
}
|
|
|
|
if(pDef == (JET_TABLECREATE*)-1)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, tbl->Create());
|
|
}
|
|
else
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, tbl->Create( pDef ));
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(tblNew) delete tblNew;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT JetBlue::Database::Compact()
|
|
{
|
|
__HCP_FUNC_ENTRY( "JetBlue::Database::Compact" );
|
|
|
|
HRESULT hr;
|
|
JET_DBUTIL util;
|
|
CHAR rgTempDB[MAX_PATH];
|
|
|
|
::ZeroMemory( &util, sizeof(util) );
|
|
|
|
util.cbStruct = sizeof(util);
|
|
util.sesid = m_sesid;
|
|
util.op = opDBUTILDBDefragment;
|
|
util.szDatabase = (LPSTR)m_strName.c_str();
|
|
util.szTable = rgTempDB;
|
|
|
|
StringCbPrintfA( rgTempDB, sizeof(rgTempDB), "%s.temp", util.szDatabase );
|
|
(void)::DeleteFileA( rgTempDB );
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Close());
|
|
|
|
|
|
__MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetDBUtilities( &util ));
|
|
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::MoveFileExA( rgTempDB, util.szDatabase, MOVEFILE_REPLACE_EXISTING ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
(void)::DeleteFileA( rgTempDB );
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT JetBlue::Database::Repair()
|
|
{
|
|
__HCP_FUNC_ENTRY( "JetBlue::Database::Repair" );
|
|
|
|
HRESULT hr;
|
|
JET_DBUTIL util;
|
|
|
|
::ZeroMemory( &util, sizeof(util) );
|
|
|
|
util.cbStruct = sizeof(util);
|
|
util.sesid = m_sesid;
|
|
util.op = opDBUTILEDBRepair;
|
|
util.szDatabase = (LPSTR)m_strName.c_str();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Close());
|
|
|
|
|
|
__MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetDBUtilities( &util ));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
JetBlue::Table* JetBlue::Database::GetTbl( /*[in]*/ int iPos )
|
|
{
|
|
for(TableIter it = m_mapTables.begin(); it != m_mapTables.end(); it++)
|
|
{
|
|
if(iPos-- == 0) return it->second;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
JetBlue::Table* JetBlue::Database::GetTbl( LPCSTR szTbl )
|
|
{
|
|
TableIter it = m_mapTables.find( szTbl );
|
|
|
|
return (it == m_mapTables.end()) ? NULL : it->second;
|
|
}
|