OLE DB Programmer's Reference |
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, pwszQuery) { HRESULT hr; struct COLUMNDATA { SDWORD 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. ULONG cAxis; MDAXISINFO* rgAxisInfo = NULL; hr = pIMDDataset->GetAxisInfo( &cAxis, &rgAxisInfo ); for (ULONG iAxis=0; iAxis < cAxis; iAxis++) { // rgAxisInfo contains the array of dimensions for each axis. for (ULONG 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->GetAxisRowse(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); ULONG 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. ULONG dwOffset = 0; ULONG iBind = 0; ULONG cBind = 0; DBBINDING* rgBind = (DBBINDING*)CoTaskMemAlloc( cCol*sizeof(DBBINDING)); for (ULONG 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. ULONG 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. ULONG cRowsObtained; hr = pIRowset->GetNextRows(NULL, 0, 20, &cRowsObtained, &pRows); // Break on EndOfRowset. if (cRowsObtained == 0) break; for (ULONG 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; }
1998-2001 Microsoft Corporation. All rights reserved.