神通数据库 OLE DB枚举器¶
神通数据库 OLE DB提供一个枚举器组件,用户可以使用它得到网络中所有可用神通数据库 OLE DB连接上的数据源列表。枚举器组件由GUID CLSID_OSCAROLEDB_ENUMERATOR = {}来标识。
下面举例说明。枚举SHENTONG OLE DB 数据源的步骤如下:
通过调用 ISourceRowset::GetSourcesRowset 检索源行集。
通过调用 GetColumnInfo::IcolumnInfo 查找对枚举符行集的描述。
根据列信息创建绑定结构。
通过调用 IAccessor::CreateAccessor 创建行集存取程序。
通过调用 IRowset::GetNextRows 提取行。
通过调用 IRowset::GetData 从行集的行复本中检索数据并对数据进行处理。
//How to use the enumerator object to list
//the data sources available.
#define UNICODE
#define _UNICODE
#define DBINITCONSTANTS
#define INITGUID
#include <windows.h>
#include <stddef.h>
#include <oledb.h>
#include <oledberr.h>
#include <SQLOLEDB.h>
#include <stdio.h>
#define NUMROWS_CHUNK 5
//AdjustLen supports binding on four-byte boundaries.
_inline ULONG AdjustLen(ULONG cb)
{
return ((cb + 3) & ~3);
}
// Get the characteristics of the rowset (the IColumnsInfo interface).
HRESULT GetColumnInfo
(
IRowset* pIRowset,
UINT* pnCols,
DBCOLUMNINFO** ppColumnsInfo,
OLECHAR** ppColumnStrings
)
{
IColumnsInfo* pIColumnsInfo;
HRESULT hr;
*pnCols = 0;
if (FAILED(pIRowset->QueryInterface(IID_IColumnsInfo,
(void**) &pIColumnsInfo)))
{
return (E_FAIL);
}
hr = pIColumnsInfo->GetColumnInfo((ULONG*) pnCols,
ppColumnsInfo,
ppColumnStrings);
if (FAILED(hr))
{
//Process error.
}
pIColumnsInfo->Release();
return (hr);
}
// Create binding structures from column information. Binding structures
// will be used to create an accessor that allows row value retrieval.
void CreateDBBindings
(
UINT nCols,
DBCOLUMNINFO* pColumnsInfo,
DBBINDING** ppDBBindings,
BYTE** ppRowValues
)
{
ULONG nCol;
ULONG cbRow = 0;
ULONG cbCol;
DBBINDING* pDBBindings;
BYTE* pRowValues;
pDBBindings = new DBBINDING[nCols];
for (nCol = 0; nCol < nCols; nCol++)
{
pDBBindings[nCol].iOrdinal = nCol+1;
pDBBindings[nCol].pTypeInfo = NULL;
pDBBindings[nCol].pObject = NULL;
pDBBindings[nCol].pBindExt = NULL;
pDBBindings[nCol].dwPart = DBPART_VALUE;
pDBBindings[nCol].dwMemOwner =
DBMEMOWNER_CLIENTOWNED;
pDBBindings[nCol].eParamIO = DBPARAMIO_NOTPARAM;
pDBBindings[nCol].dwFlags = 0;
pDBBindings[nCol].wType = pColumnsInfo[nCol].wType;
pDBBindings[nCol].bPrecision = pColumnsInfo[nCol].bPrecision;
pDBBindings[nCol].bScale = pColumnsInfo[nCol].bScale;
cbCol = pColumnsInfo[nCol].ulColumnSize;
switch (pColumnsInfo[nCol].wType)
{
case DBTYPE_STR:
{
cbCol += 1;
break;
}
case DBTYPE_WSTR:
{
cbCol = (cbCol + 1) * sizeof(WCHAR);
break;
}
default:
break;
}
pDBBindings[nCol].obValue = cbRow;
pDBBindings[nCol].cbMaxLen = cbCol;
cbRow += AdjustLen(cbCol);
}
pRowValues = new BYTE[cbRow];
*ppDBBindings = pDBBindings;
*ppRowValues = pRowValues;
return;
}
int main()
{
ISourcesRowset* pISourceRowset = NULL;
IRowset* pIRowset = NULL;
IAccessor* pIAccessor = NULL;
DBBINDING* pDBBindings = NULL;
HROW* pRows = new HROW[500];
BYTE* pData = NULL;
HACCESSOR hAccessorRetrieve = NULL;
ULONG cRows = 0;
ULONG DSSeqNumber = 0;
HRESULT hr;
UINT nCols;
DBCOLUMNINFO* pColumnsInfo = NULL;
OLECHAR* pColumnStrings = NULL;
DBBINDSTATUS* pDBBindStatus = NULL;
BYTE* pRowValues = NULL;
ULONG cRowsObtained;
ULONG iRow;
char* pMultiByte = NULL;
short* psSourceType = NULL;
BYTE* pDatasource = NULL;
//Initialize COM library.
CoInitialize(NULL);
//Initialize the enumerator.
if(FAILED(CoCreateInstance(CLSID_OSCAROLEDB_ENUMERATOR,
NULL,
CLSCTX_INPROC_SERVER,
IID_ISourcesRowset,
(void**)&pISourceRowset)))
{
//Process error.
return TRUE;
}
//Retrieve the source rowset.
hr = pISourceRowset->GetSourcesRowset(NULL,
IID_IRowset,
0,
NULL,
(IUnknown**)&pIRowset);
pISourceRowset->Release();
if(FAILED(hr))
{
//Process error.
return TRUE;
}
//Get the description of the enumerator's rowset.
if(FAILED(hr = GetColumnInfo(pIRowset,
&nCols,
&pColumnsInfo,
&pColumnStrings)))
{
//Process error.
goto SAFE_EXIT;
}
//Create the binding structures.
CreateDBBindings(nCols,
pColumnsInfo,
&pDBBindings,
&pRowValues);
pDBBindStatus = new DBBINDSTATUS[nCols];
if (sizeof(TCHAR) != sizeof(WCHAR))
{
pMultiByte = new char[pDBBindings[0].cbMaxLen];
}
if(FAILED(pIRowset->QueryInterface(IID_IAccessor,
(void**)&pIAccessor)))
{
//Process error.
goto SAFE_EXIT;
}
//Create the rowset accessor.
if(FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
nCols,
pDBBindings,
0,
&hAccessorRetrieve,
pDBBindStatus)))
{
//Process error.
goto SAFE_EXIT;
}
//Process all the rows, NUMROWS_CHUNK rows at a time.
while (SUCCEEDED(hr))
{
hr=pIRowset->GetNextRows(NULL,
0,
NUMROWS_CHUNK,
&cRowsObtained,
&pRows);
if(FAILED(hr))
{
//process error
}
if(cRowsObtained == 0 || FAILED(hr))
break;
for(iRow = 0; iRow < cRowsObtained; iRow++)
{
//Get the rowset data.
if(SUCCEEDED(hr = pIRowset->GetData(pRows[iRow],
hAccessorRetrieve,
pRowValues)))
{
psSourceType = (short *)(pRowValues +
pDBBindings[3].obValue);
if (*psSourceType == DBSOURCETYPE_DATASOURCE)
{
DSSeqNumber = DSSeqNumber + 1;
//Data source counter.
pDatasource = (pRowValues +
pDBBindings[0].obValue);
if(sizeof(TCHAR) != sizeof(WCHAR))
{
WideCharToMultiByte(CP_ACP, 0,
(WCHAR*)pDatasource, -1, pMultiByte,
pDBBindings[0].cbMaxLen, NULL, NULL);
printf( "DataSource# %d\tName: %S\n",
DSSeqNumber, (WCHAR *) MultiByte );
}
else
{
printf( "DataSource# %d\tName: %S\n",
DSSeqNumber, (WCHAR *) pDatasource );
} //if
} //if
} //if
} //for
pIRowset->ReleaseRows(cRowsObtained, pRows, NULL,
NULL, NULL);
} //while
//Release COM library.
CoUninitialize();
return(0);
SAFE_EXIT:
//Do the clean-up.
return TRUE;
};