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.
MDPDataset is used to get the cell data for an MDX query specified by pwszQuery, compute the cell data coordinates, and call IMDDataset::GetCellData for each cell in the dataset.
//
HRESULT MDPDataset(ICommandText *pICommandText, LPCOLESTR pwszQuery)
{
HRESULT hr;
struct COLUMNDATA
{
DWORD dwLength; // length of data (not space allocated)
DBSTATUS dwStatus; // status of column
VARIANT var; // variant value
};
// Execute the MDX query.
IMDDataset* pIMDDataset = NULL;
hr = pICommandText->SetCommandText(DBGUID_MDX, pwszQuery);
hr = pICommandText->Execute(NULL, IID_IMDDataset, NULL, NULL,
(IUnknown **)&pIMDDataset );
// Fetch the axis info to compute the coordinates.
DBCOUNTITEM cAxis;
MDAXISINFO* rgAxisInfo = NULL;
hr = pIMDDataset->GetAxisInfo( &cAxis, &rgAxisInfo );
// Calculate the coordinate "offset factors". These are used to
// translate from a point in cell space to a set of axis coordinates.
// Example, consider a dataset with three axes and the following
// number of coordinates for each axis:
// {x,y,z} = {3,4,5}
// rgAxisOffset[2] = 3*4
// rgAxisOffset[1] = 3
// rgAxisOffset[0] = 1
// Thus, where p represents the cell's ordinal value:
// z = p % 12
// y = (p - z*12) % 3
// x = (p - z*12 - y*3)
// And,
// p = x + 3*y + 12*z
DBCOUNTITEM cAxisTuple;
DBORDINAL iOffset = 1;
DBORDINAL ulMaxCoord = 0;
DBORDINAL rgAxisOffset[MAX_DIMS]; // array of offset multipliers
// For all axes, excluding the slicer axis if present.
for (DBCOUNTITEM iAxis=0; iAxis < cAxis; iAxis++)
{
// Skip the slicer axis.
if (rgAxisInfo[iAxis].iAxis == MDAXIS_SLICERS) continue;
rgAxisOffset[iAxis] = iOffset;
cAxisTuple = rgAxisInfo[iAxis].cCoordinates;
iOffset *= cAxisTuple;
}
ulMaxCoord = iOffset;
// Bind to the column values for each cell.
IColumnsInfo *pIColumnsInfo = NULL;
hr = pIMDDataset->QueryInterface(IID_IColumnsInfo,
(void**)&pIColumnsInfo);
DBORDINAL cCol;
WCHAR* pStringsBuffer = NULL;
DBCOLUMNINFO* pInfo = NULL;
hr = pIColumnsInfo->GetColumnInfo(&cCol, &pInfo, &pStringsBuffer);
// Allocate size for rgBind
DBBINDING* rgBind;
rgBind = (DBBINDING*)CoTaskMemAlloc(cCol * sizeof(DBBINDING));
// Create bindings for each cell's columns, ordered as returned by
// GetColumnInfo. Bind everything as Variant.
DWORD dwOffset = 0;
DBCOUNTITEM iBind = 0;
DBCOUNTITEM cBind = 0;
for (DBORDINAL iCol=0; iCol < cCol; iCol++)
{
rgBind[iBind].iOrdinal = pInfo[iCol].iOrdinal;
rgBind[iBind].obValue = dwOffset +
offsetof(COLUMNDATA,var);
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 = sizeof(VARIANT);
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].wType = DBTYPE_VARIANT;
rgBind[iBind].bPrecision = 0;
rgBind[iBind].bScale = 0;
dwOffset += rgBind[iBind].cbMaxLen + offsetof(COLUMNDATA,var);
iBind++;
}
cBind = iBind;
// Create the accessor.
IAccessor* pIAccessor;
hr = pIMDDataset->QueryInterface(IID_IAccessor, (void**)&pIAccessor);
// Note that the value of dwOffset contains the size of a cell.
// Failure to specify this value will result in an error.
hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBind, rgBind,
dwOffset, phAccessor, NULL);
pIAccessor->Release();
pIColumnsInfo->Release();
// Allocate a buffer for a single cell in a slice.
DBLENGTH cbRowsize = dwOffset;
pData = (BYTE*)CoTaskMemAlloc(cbRowSize);
// Fetch each cell in the dataset.
for (DBORDINAL ulCellCoord=0; ulCellCoord < ulMaxCoord; ulCellCoord++)
{
// Populate cell buffer.
hr = pIMDDataset->GetCellData(hAccessor, ulCellCoord, ulCellCoord,
pData);
// Traverse each bound cell property value for a single cell "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);
// pColumn->var points to the variant value.
::VariantClear(&(pColumn->var));
}
}
// Free the accessor and rowset.
hr = pIAccessor->ReleaseAccessor(hAccessor, NULL);
hr = pIAccessor->Release();
hr = pIColumnsInfo->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;
}