2025-11-28 00:35:46 +09:00

353 lines
12 KiB
C++

// Start of file MSOmniProvRS.cpp
// File: MSOmniProvRS.cpp
//
// This file contains the implementation for the CMSOmniProvRowset and CMSOmniProvCommand
//
// The following functions have been customized or added for the provider to function:
//
// CMSOmniProvCommand :: Execute - Executes the command...
// CMSOmniProvCommand :: GetColumnsInfo - Returns the column metadata requested by the consumer...
// CMSOmniProvRowset :: Execute - Parses the SQL query, executes it and builds the initial rowset...
// CMSOmniProvRowset :: GetColumnInfo - Returns the column metadata requested by the consumer builds reading the schema '.sxt' file...
// CMSOmniProvRowset :: CreateColInfo - Creates all of the column information and stores it in the rowset...
// CMSOmniProvRowset :: AllocateProxyBuffers - Causes the proxy buffers to be allocated for each of the CRow objects...
// CMSOmniProvRowset :: GetSchemaInfo - Returns the column metadata about the rowset...
// CMSOmniProvRowset :: CheckTable - Finds if the table in the Query exists or not...
// CMSOmniProvRowset :: GetDataSource - Retrieves the file name including the path to the schema '.sxt' file...
//
#include "stdafx.h"
#include "TheProvider.h" // Contains the definitions for the interfaces
#include "MSOmniProvRS.h" // Command and rowset header file
#include <comdef.h> // For _bstr_t
// CMSOmniProvCommand
// CMSOmniProvCommand :: Execute
// Executes the command...
HRESULT CMSOmniProvCommand::Execute(IUnknown * pUnkOuter, REFIID riid, DBPARAMS * pParams,
DBROWCOUNT * pcRowsAffected, IUnknown ** ppRowset)
{
CMSOmniProvRowset* pRowset;
return CreateRowset(pUnkOuter, riid, pParams, pcRowsAffected, ppRowset, pRowset);
}
// CMSOmniProvCommand :: GetColumnsInfo
// Returns the column metadata requested by the consumer...
ATLCOLUMNINFO* CMSOmniProvCommand::GetColumnInfo(CMSOmniProvCommand* pv, DBORDINAL* pcInfo)
{
return NULL;
}
// CMSOmniProvRowset
// CMSOmniProvRowset::Execute
// 1. Parse the SQL query,
// 2. Execute the query, and
// 3. Build the initial rowset
HRESULT CMSOmniProvRowset::Execute(DBPARAMS * pParams, DBROWCOUNT* pcRowsAffected)
{
USES_CONVERSION;
CMSOmniProvRowset* pT = (CMSOmniProvRowset*) this;
CMSOmniProvRowset::ObjectLock cab((CMSOmniProvRowset*) this);
HRESULT hr;
_bstr_t m_bstrFileName;
if ( FAILED(hr=pT->GetDataSource(m_bstrFileName)) )
return hr;
// Check the property value whether read/ updatabiliy property is set or not...
_variant_t varUpd;
GetPropValue(&DBPROPSET_ROWSET,DBPROP_UPDATABILITY, &varUpd);
if ( 0 != varUpd.iVal )
{
// 1. a) Build the file's Schema m_prgColInfo from the '.sxt' file,
// b) Open the file '.txt', and
// c) Fill the m_DBFile.m_Rows structure
// Open in exclusive mode
if (!m_DBFile.Open((LPCTSTR) m_bstrFileName,true))
return DB_E_NOTABLE;
if (!m_DBFile.FillRowArray())
return E_FAIL;
}
else // Open in non-exclusive mode
{
if (!m_DBFile.Open((LPCTSTR) m_bstrFileName,false))
return DB_E_NOTABLE;
if (!m_DBFile.FillRowArray())
return E_FAIL;
}
// Validate Command
// 2. PARSE the SQL Query here (Only SELECT * FROM <Table_Name> is supported)
TCHAR sep[] = " ";
_bstr_t bstrSQL(pT->m_strCommandText);
LPTSTR pchNextToken = NULL;
TCHAR * token = _tcstok_s((TCHAR*) bstrSQL, (TCHAR*) sep, &pchNextToken);
if (!CheckTable((TCHAR*) token))
{
// The Rowset was created using the ICommand::Execute( )...
// Only "SELECT * FROM Table_Name" Queries are supported
if(_tcsicmp(token,TEXT("select")) != 0)
{
ATLTRACE2(atlTraceDBProvider,0,(const TCHAR*) (_bstr_t("Query: '")+ bstrSQL + _bstr_t("' is not a valid Query\n")));
return DB_E_ERRORSINCOMMAND;
}
ATLTRACE2(atlTraceDBProvider,0,(const TCHAR*) (_bstr_t("\tIt is a valid '")+_bstr_t(token) + _bstr_t("' Query\n")));
TCHAR szTblNm[MAX_TABLE_NAME_SIZE];
while (token != NULL)
{
_tcscpy_s(szTblNm, _countof(szTblNm), token);
token= _tcstok_s(NULL,(TCHAR*) sep, &pchNextToken);
}
if (!CheckTable((TCHAR*) szTblNm))
return DB_E_NOTABLE;
}
// Allocate proxy buffers based on the schema information
// Each CRow contains proxy buffer that the data is trasnferred to in the native
// format. This information then needs to be copied out to the file in character format
// on SetData() calls.
CreateColInfo();
AllocateProxyBuffers();
if (pcRowsAffected != NULL)
*pcRowsAffected = m_DBFile.m_Rows.GetCount();
return S_OK;
}
// CMSOmniProvRowset :: GetColumnInfo
// Overriding GetColumnInfo as we will be deriving the column information
// from the schema '.sxt' file
ATLCOLUMNINFO* CMSOmniProvRowset::GetColumnInfo(CMSOmniProvRowset* pv, DBORDINAL* pNumCols)
{
ATLASSERT(pv!=NULL);
ATLASSERT(pNumCols!=NULL);
return pv->GetSchemaInfo(pNumCols);
}
// CMSOmniProvRowset :: CreateColInfo
// This function creates all of the column information and stores it in the rowset.
// It currently uses all of the columns of the table
void CMSOmniProvRowset::CreateColInfo()
{
// check if bookmarks are set
bool bUseBookmarks = false;
CComVariant varBookmarks;
HRESULT hrLocal = GetPropValue(&DBPROPSET_ROWSET, DBPROP_BOOKMARKS, &varBookmarks);
bUseBookmarks = (hrLocal == S_OK && varBookmarks.boolVal == VARIANT_TRUE);
// get column info from the .INI file
DBORDINAL ulNumCols;
ATLCOLUMNINFO * prgColInfo = m_DBFile.GetSchemaInfo(&ulNumCols);
// Need to add bookmark column info?
if (bUseBookmarks)
{
// create new set of column information which includes bookmarks
ATLCOLUMNINFO * prgColInfoNew;
prgColInfoNew = new ATLCOLUMNINFO[ulNumCols+1];
// set bindings for the bookmark
memset(&prgColInfoNew[0], 0, sizeof(ATLCOLUMNINFO));
prgColInfoNew[0].cbOffset = 0;
prgColInfoNew[0].iOrdinal = 0;
prgColInfoNew[0].columnid.eKind = DBKIND_NAME;
prgColInfoNew[0].columnid.uGuid.guid = GUID_NULL;
prgColInfoNew[0].columnid.uName.pwszName = OLESTR("Bookmark");
prgColInfoNew[0].pwszName = OLESTR("Bookmark");
prgColInfoNew[0].wType = DBTYPE_I4;
prgColInfoNew[0].ulColumnSize = 4;
prgColInfoNew[0].dwFlags = DBCOLUMNFLAGS_ISBOOKMARK;
// copy the old information into the new
for (DBORDINAL i = 1; i <= ulNumCols; i++)
{
prgColInfoNew[i] = prgColInfo[i-1];
prgColInfoNew[i].cbOffset +=4; //adjust space for bookmark
}
ulNumCols++;
prgColInfo = prgColInfoNew;
}
// store column info in the rowset object
SetSchemaInfo(prgColInfo, ulNumCols);
// 2.0
// Release the temporary prgColInfo
delete [] prgColInfo;
}
// CMSOmniProvRowset :: AllocateProxyBuffers
// Causes the proxy buffers to be allocated for each of the CRow objects
// which represents one row of the file.
void CMSOmniProvRowset::AllocateProxyBuffers()
{
CAtlArray<CRow *> * pRows = &m_DBFile.m_Rows;
size_t nSize = pRows->GetCount();
for (size_t i = 0; i < nSize; i++)
{
(*pRows)[i]->AllocProxyBuffer(m_prgColInfo, m_cCols);
}
}
// CMSOmniProvRowset :: GetSchemaInfo
// Returns the column metadata about the rowset...
ATLCOLUMNINFO * CMSOmniProvRowset::GetSchemaInfo(DBORDINAL * pNumCols)
{
// Allocate the column information only once as the functions we are returning the
// data from don't free.
*pNumCols = m_cCols;
return m_prgColInfo;
}
// CMSOmniProvRowset :: CheckTable
// Finds if the table in the Query exists or not...
// 2.0
// Code to recognize table name enclosed in [ ]...
BOOL CMSOmniProvRowset::CheckTable(TCHAR* szTblNm)
{
CMSOmniProvRowset* pT = (CMSOmniProvRowset*) this;
if(szTblNm[0] == '[')
{
size_t iLenBuff = 0;
iLenBuff = _tcslen(szTblNm);
TCHAR *szTmpBuff= (TCHAR *) malloc(sizeof(TCHAR) *iLenBuff );
_tcsncpy_s(szTmpBuff, iLenBuff, szTblNm + 1,iLenBuff -2);
if (!_tcscmp(pT->m_DBFile.m_szTblNm, szTmpBuff))
{
free(szTmpBuff);
return true;
}
else
free(szTmpBuff);
}
if (!_tcscmp(pT->m_DBFile.m_szTblNm, szTblNm))
return true;
else
return false;
}
//CMSOmniProvRowset :: GetDataSource
// Retrieves the file name including the path to the schema '.sxt' file...
HRESULT CMSOmniProvRowset::GetDataSource(_bstr_t &m_bstrLoc)
{
CMSOmniProvRowset* pT = (CMSOmniProvRowset*) this;
CMSOmniProvRowset::ObjectLock cab((CMSOmniProvRowset*) this);
CComPtr<IDBCreateCommand> spSession = NULL;
CComPtr<IRowset> spRowset = NULL;
HRESULT hr = pT->GetSite(IID_IDBCreateCommand, (void**) &spSession);
if (SUCCEEDED(hr)) // The Rowset was created from an IOpenRowset::OpenRowset( )...
{
// Get to DBPROP_INIT_DATASOURCE property
CComPtr<IDBCreateSession> spInit;
CComPtr<IObjectWithSite> spCreator2 = NULL;
if (FAILED(hr = spSession->QueryInterface(IID_IObjectWithSite,(void**) &spCreator2)))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IObjectWithSite from ICommand...\n");
return E_FAIL;
}
if (FAILED(hr = spCreator2->GetSite(IID_IDBCreateSession,(void**) &spInit)))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IDBCreateSession from ICommand...\n");
return E_FAIL;
}
// Initialize the property variables
ULONG cPropertyIDSets =1;
DBPROPIDSET rgPropertyIDSets[1];
ULONG cPropertySets;
DBPROPSET * prgPropertySets;
DBPROPID rgPropId[1];
rgPropId[0] = DBPROP_INIT_DATASOURCE;
rgPropertyIDSets[0].rgPropertyIDs = rgPropId;
rgPropertyIDSets[0].cPropertyIDs = 1;
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DBINIT;
CComPtr<IDBProperties> spProperties = NULL;
hr = spInit->QueryInterface(IID_IDBProperties,(void**) &spProperties);
if(FAILED(hr))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IDBCreateSession'ss IDBProperties...\n");
return hr;
}
spProperties->GetProperties(cPropertyIDSets, rgPropertyIDSets,&cPropertySets, &prgPropertySets) ;
m_bstrLoc = _bstr_t(prgPropertySets->rgProperties[0].vValue);
}
else // The Rowset was created from ICommand::Execute( )
{
CComPtr<ICommand> spCommand=NULL;
hr = pT->GetSite(IID_ICommand,(void**) &spCommand);
if(FAILED(hr))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the ICommand of the Rowset...\n");
return E_FAIL;
}
CComPtr<IObjectWithSite> spCreator = NULL;
if (FAILED(hr = spCommand->QueryInterface(IID_IObjectWithSite,(void**) &spCreator)))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IObjectWithSite from ICommand...\n");
return E_FAIL;
}
if (FAILED(hr = spCreator->GetSite(IID_IDBCreateCommand,(void**) &spSession)))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IDBCreateSession from ICommand...\n");
return E_FAIL;
}
CComPtr<IDBCreateSession> spInit;
CComPtr<IObjectWithSite> spCreator2 = NULL;
if (FAILED(hr = spSession->QueryInterface(IID_IObjectWithSite,(void**) &spCreator2)))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IObjectWithSite from ICommand...\n");
return E_FAIL;
}
if (FAILED(hr = spCreator2->GetSite(IID_IDBCreateSession,(void**) &spInit)))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IDBCreateSession from ICommand...\n");
return E_FAIL;
}
// Get to DBPROP_INIT_DATASOURCE
ULONG cPropertyIDSets =1;
DBPROPIDSET rgPropertyIDSets[1];
ULONG cPropertySets;
DBPROPSET * prgPropertySets;
DBPROPID rgPropId[1];
rgPropId[0] = DBPROP_INIT_DATASOURCE;
rgPropertyIDSets[0].rgPropertyIDs = rgPropId;
rgPropertyIDSets[0].cPropertyIDs = 1;
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DBINIT;
CComPtr<IDBProperties> spProperties = NULL;
hr = spInit->QueryInterface(IID_IDBProperties,(void**) &spProperties);
if(FAILED(hr))
{
ATLTRACE2(atlTraceDBProvider,0,"FATAL ERROR: Cannot get to the IDBCreateSession'ss IDBProperties...\n");
return hr;
}
spProperties->GetProperties(cPropertyIDSets, rgPropertyIDSets,&cPropertySets, &prgPropertySets) ;
m_bstrLoc = _bstr_t(prgPropertySets->rgProperties[0].vValue);
}
return hr;
}
// End of file MSOmniProvRS.cpp