Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This function executes an MDX query statement specified by pwszQuery. IMDDataset::GetAxisInfo and IMDDataset::GetAxisRowset are called to traverse the column information for each axis in the MDX query.
HRESULT MDPQueryColumnInfo(ICommandText *pICommandText, LPCOLESTR pwszQuery)
{
HRESULT hr;
struct COLUMNDATA
{
DWORD dwLength; // length of data
DBSTATUS dwStatus; // status of column
SHORT wPadding;
BYTE bData[1]; // variable-length data
};
// Execute the query.
IMDDataset* pIMDDataset = NULL;
hr = pICommandText->SetCommandText(DBGUID_MDX, pwszQuery);
hr = pICommandText->Execute(NULL, IID_IMDDataset, NULL, NULL,
(IUnknown **)&pIMDDataset );
// Fetch and traverse the axis info.
DBCOUNTITEM cAxis;
MDAXISINFO* rgAxisInfo = NULL;
hr = pIMDDataset->GetAxisInfo( &cAxis, &rgAxisInfo );
for (DBCOUNTITEM iAxis=0; iAxis < cAxis; iAxis++)
{
// rgAxisInfo contains the array of dimensions for each axis.
for (DBCOUNTITEM iDim=0; iDim < rgAxisInfo[iAxis].cDimensions; iDim++)
{
// MDAXISINFO_GETAT(rgAxisInfo, iAxis).rgpwszDimensionNames points
// to the dimension name.
assert( MDAXISINFO_GETAT(rgAxisInfo, iAxis).rgpwszDimensionNames);
}
// Fetch the axis rowset for each axis.
IRowset* pIrowset = NULL;
hr = pIMDDataset->GetAxisRowset(NULL, iAxis,
IID_IRowset, 0, NULL, (IUnknown**)&pIRowset);
// Fetch the column info for the axis rowset.
IColumnsInfo *pIColumnsInfo = NULL;
hr = pIRowset->QueryInterface(IID_IColumnsInfo,
(void**)&pIColumnsInfo);
DBCOUNTITEM cCol;
WCHAR* pStringsBuffer = NULL;
DBCOLUMNINFO* pInfo = NULL;
hr = pIColumnsInfo->GetColumnInfo(&cCol, &pInfo, &pStringsBuffer);
// Create bindings for all columns, in same order as given by
// GetColumnInfo. Bind everything as string, and skip DBTYPE_VECTOR
// type columns.
DBBYTEOFFSET dwOffset = 0;
DBCOUNTITEM iBind = 0;
DBCOUNTITEM cBind = 0;
DBBINDING* rgBind = (DBBINDING*)CoTaskMemAlloc(
cCol*sizeof(DBBINDING));
for (DBCOUNTITEM iCol=0; iCol < cCol; iCol++)
{
// Skip columns of type _VECTOR (probably binary data).
if (pInfo[iCol].wType & DBTYPE_VECTOR)
continue;
rgBind[iBind].iOrdinal = pInfo[iCol].iOrdinal;
rgBind[iBind].obValue = dwOffset +
offsetof(COLUMNDATA,bData);
rgBind[iBind].obLength = dwOffset +
offsetof(COLUMNDATA,dwLength);
rgBind[iBind].obStatus = dwOffset +
offsetof(COLUMNDATA,dwStatus);
rgBind[iBind].pTypeInfo = NULL;
rgBind[iBind].pObject = NULL;
rgBind[iBind].pBindExt = NULL;
rgBind[iBind].cbMaxLen = pInfo[iCol].ulColumnSize;
rgBind[iBind].dwFlags = 0;
rgBind[iBind].eParamIO = DBPARAMIO_NOTPARAM;
rgBind[iBind].dwPart = DBPART_VALUE |
DBPART_LENGTH |
DBPART_STATUS;
rgBind[iBind].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
rgBind[iBind].bPrecision = 0;
rgBind[iBind].bScale = 0;
rgBind[iBind].wType = DBTYPE_STR;
dwOffset += rgBind[iBind].cbMaxLen +
offsetof(COLUMNDATA,bData);
iBind++;
}
cBind = iBind;
// Create the accessor.
IAccessor* pIAccessor;
hr = pIRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor);
hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBind, rgBind,
dwOffset, phAccessor, NULL);
// Allocate a buffer for a single row of data.
DBLENGTH cbRowsize = dwOffset;
BYTE* pData = (BYTE *)CoTaskMemAlloc(cbRowSize);
while (SUCCEEDED(hr))
{
// Prepare internal buffers and get handles to the rows.
// Fetch 20 rows at a time.
DBCOUNTITEM cRowsObtained;
hr = pIRowset->GetNextRows(NULL, 0, 20, &cRowsObtained, &pRows);
// Break on EndOfRowset.
if (cRowsObtained == 0) break;
for (DBCOUNTITEM iRow=0; iRow < cRowsObtained; iRow++)
{
// Clear buffer.
memset(pData, 0, cbRowSize);
// Get the row data.
hr = pIRowset->GetData(rghRows[iRow], hAccessor, pData);
// Traverse each bound column value for a single row.
// Use pColumn to access each column's data values.
for (iBind=0; iBind < cBind; iBind++)
{
// Advance to the column value.
(COLUMNDATA*)pColumn = (COLUMNDATA *)(pData +
rgBind[iBind].obLength);
// (WCHAR*)pColumn->bData points to the string value.
}
}
// Release the row handles.
hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL,
NULL);
}
// Free the accessor and rowset.
hr = pIAccessor->ReleaseAccessor(hAccessor, NULL);
hr = pIAccessor->Release();
hr = pIRowset->Release();
// Free the row data and bindings.
CoTaskMemFree(pData);
CoTaskMemFree(rgBind);
// Free the column info.
CoTaskMemFree(pInfo);
CoTaskMemFree(pwszStringsBuffer);
}
hr = pIMDDataset->FreeAxisInfo(cAxis, rgAxisInfo);
hr = pIMDDataset->Release();
return hr;
}