OLE DB Programmer's Reference |
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, pwszQuery) { HRESULT hr; struct COLUMNDATA { SDWORD 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. ULONG 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 ULONG cAxisTuple; ULONG iOffset = 1; ULONG ulMaxCoord = 0; ULONG rgAxisOffset[MAX_DIMS]; // array of offset multipliers // For all axes, excluding slicer axis... for (ULONG iAxis=0; iAxis < cAxis-1; iAxis++) { rgAxisOffset[iAxis] = iOffset; cAxisTuple = rgAxisInfo[iAxis].cCoordinates; iOffset *= cAxisTuple; } ulMaxCoord = iOffset; ULONG cSliceCoord = rgAxisOffset[cAxis-1] // Bind to the column values for each cell. IColumnsInfo *pIColumnsInfo = NULL; hr = pIMDDataset->QueryInterface(IID_IColumnsInfo, (void**)&pIColumnsInfo); ULONG cCol; WCHAR* pStringsBuffer = NULL; DBCOLUMNINFO* pInfo = NULL; hr = pIColumnsInfo->GetColumnInfo(&cCol, &pInfo, &pStringsBuffer); // Create bindings for each cell's columns, ordered as returned by // GetColumnInfo. Bind everything as Variant. dwOffset = 0; ULONG iBind = 0; ULONG cBind = 0; for (ULONG 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. ULONG cbRowsize = dwOffset; pData = (BYTE*)CoTaskMemAlloc(cbRowSize); // Fetch each cell in the dataset. for (ULONG 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. } } // 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; }
1998-2001 Microsoft Corporation. All rights reserved.