/////////////////////////////////////////////////////////////////////////////////// // // Microsoft WMIOLE DB Provider // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved. // // CQualifierRowFetchObj object implementation // // /////////////////////////////////////////////////////////////////////////////////// #include "headers.h" #include "WmiOleDBMap.h" /////////////////////////////////////////////////////////////////////////////////////// // Function which fetches required number of rows /////////////////////////////////////////////////////////////////////////////////////// HRESULT CQualifierRowFetchObj::FetchRows(CRowset * pRowset, HCHAPTER hChapter, // IN The Chapter handle. DBROWOFFSET lRowOffset, // IN Rows to skip before reading DBROWCOUNT cRows, // IN Number of rows to fetch DBCOUNTITEM* pcRowsObtained, // OUT Number of rows obtained HROW ** prghRows) // OUT Array of Hrows obtained) { DBCOUNTITEM cRowsTmp = 0; HROW irow, ih; PROWBUFF prowbuff = NULL; HRESULT hr = S_OK; HROW * prghRowsTemp = NULL; HROW hRowCurrent = 0; HSLOT hSlot = -1; BOOL bAlreadyDataRetrieved = FALSE; BOOL bAlreadyFetched = FALSE; CVARIANT varKey; BOOL bFetchBack = FALSE; HROW hRowTemp; BSTR strQualifier; CBSTR strKey; LONG_PTR lFetchPos = 0; BOOL bHRowsAllocated = FALSE; DBROWCOUNT ulMax = 0; BOOL bMaxRowsExceed = FALSE; CWbemClassWrapper *pInst = NULL; if(cRows != 0) { { VARIANT varTemp; VariantInit(&varTemp); pRowset->GetRowsetProperty(DBPROP_MAXOPENROWS,varTemp); ulMax = varTemp.lVal; VariantClear(&varTemp); } //======================================================= // If already maximum rows are opened then return //======================================================= if( pRowset->m_ulRowRefCount >= (DBROWCOUNT)ulMax) { hr = DB_S_ROWLIMITEXCEEDED; } else { if(pRowset->m_bIsChildRs == FALSE) { assert(pRowset->m_pInstance != NULL); } //======================== // Fetch Data //======================== if (lRowOffset) { if(hChapter > 0) { pInst = pRowset->m_pChapterMgr->GetInstance(hChapter); } else if(pRowset->m_bIsChildRs == FALSE) { pInst = pRowset->m_pInstance; } //=================================== // Calculate the new position //=================================== hr = pRowset->ResetRowsetToNewPosition(lRowOffset,pInst); if( hr != S_OK ) { pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR); hr = DB_S_ENDOFROWSET ; } } if(hr == S_OK) { if(0 >( lFetchPos = GetFirstFetchPos(pRowset,cRows,lRowOffset))) { hr = DB_E_BADSTARTPOSITION; } else { cRowsTmp = cRows >= 0 ? cRows : cRows * (-1); ulMax = ulMax - pRowset->m_ulRowRefCount; if(ulMax < (DBROWCOUNT)cRowsTmp) { bMaxRowsExceed = TRUE; } else { ulMax = cRowsTmp; } cRowsTmp = 0; pRowset->m_FetchDir = (LONG_PTR)cRows < 0 ? FETCHDIRBACKWARD : FETCHDIRFORWARD; bFetchBack = (LONG_PTR)cRows < 0 ? TRUE : FALSE; // cRows = cRows >=0 ? cRows : cRows * (-1); //======================================================================= // If any rows is to be retrieved then allocate memory for the HROWS //======================================================================= if (ulMax ) { try { prghRowsTemp = (HROW *) g_pIMalloc->Alloc( ulMax * sizeof( HROW )); } catch(...) { if(prghRowsTemp != NULL) { g_pIMalloc->Free(prghRowsTemp); } throw; } } if(prghRowsTemp == NULL) { hr = E_OUTOFMEMORY; } } if(SUCCEEDED(hr)) { memset(prghRowsTemp,0,ulMax * sizeof( HROW )); hRowTemp = pRowset->m_hRowLastFetched; for (irow =1; irow <= (DBCOUNTITEM)ulMax; irow++) { bAlreadyFetched = FALSE; bAlreadyDataRetrieved = FALSE; if(pRowset->m_bIsChildRs == TRUE) { //============================================================================== // Find out whether qualifier is already obtained //============================================================================== pInst = pRowset->m_pChapterMgr->GetInstance(hChapter); pRowset->m_pChapterMgr->GetInstanceKey(hChapter,(BSTR *)&strKey); } else if( pRowset->m_pInstance != NULL) { pInst = pRowset->m_pInstance; } switch(pRowset->m_uRsType) { case CLASSQUALIFIER: hr = pRowset->GetNextClassQualifier(pInst,strQualifier,bFetchBack); break; case PROPERTYQUALIFIER: hr = pRowset->GetNextPropertyQualifier(pInst,pRowset->m_strPropertyName,strQualifier,bFetchBack); break; } if(S_OK != hr) { pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR); hr = DB_S_ENDOFROWSET; break; } if( hr == S_OK) { strKey.Clear(); strKey.Unbind(); strKey.SetStr(strQualifier); if(pRowset->m_bIsChildRs == TRUE) { hRowTemp = pRowset->m_pChapterMgr->GetHRow(hChapter,strQualifier); } else { hRowTemp = pRowset->m_InstMgr->GetHRow(strQualifier); } if( (LONG)hRowTemp > 0) { bAlreadyFetched = TRUE; } } if( bAlreadyFetched == TRUE) { hRowCurrent = hRowTemp; if(pRowset->m_bIsChildRs == TRUE) { hSlot = pRowset->m_pChapterMgr->GetSlot(hRowCurrent); } else { hSlot = pRowset->m_InstMgr->GetSlot(hRowCurrent); } if( hSlot != -1) { bAlreadyDataRetrieved = TRUE; } } //==================================================== // Get the HROW if row is not already fetched //==================================================== if( bAlreadyFetched == FALSE) hRowCurrent = pRowset->GetNextHRow(); //===================================================== // Get the data if data is already not fetched //===================================================== if(bAlreadyDataRetrieved == FALSE) { hSlot = -1; if (SUCCEEDED( hr = GetNextSlots( pRowset->m_pIBuffer, 1, &hSlot ))) { if (FAILED( pRowset->Rebind((BYTE *) pRowset->GetRowBuffFromSlot( hSlot, TRUE )))) { hr = E_FAIL; break; } } else { break; } hRowCurrent = hSlot; //================================================================================================= // if the other updates visible property is set to false ,then get the data to the local buffer //================================================================================================= if(!( pRowset->m_ulProps & OTHERUPDATEDELETE)) { if(FAILED(hr = pRowset->GetInstanceDataToLocalBuffer(pInst,hSlot,strQualifier))) { break; } //=========================================================================== // if there is atleast one row retrieved and there are neseted columns // then allocate rows for the child recordsets //=========================================================================== if(pRowset->m_cNestedCols > 0 ) { if(pRowset->m_ppChildRowsets == NULL) { pRowset->AllocateAndInitializeChildRowsets(); } //===================================================================== // Fill the HCHAPTERS for the column //===================================================================== if(S_OK != (hr = pRowset->FillHChaptersForRow(pInst,strKey))) { break; } } } if(SUCCEEDED(hr)) { //=================================================== // if the rowset is not a child rowset //=================================================== if(pRowset->m_bIsChildRs == FALSE) { //================================================= // add instance pointer to instance manager //================================================= if(FAILED(hr = pRowset->m_InstMgr->AddInstanceToList(hRowCurrent,pInst,strQualifier,hSlot))) { break; } } //================================================================================= // if rowset is refering to qualifiers then add the row to the particular chapter //================================================================================= else { // add instance pointer to instance manager if(FAILED(hr = pRowset->m_pChapterMgr->AddHRowForChapter(hChapter,hRowCurrent, NULL ,hSlot))) { break; } pRowset->m_pChapterMgr->SetInstance(hChapter,pInst, strQualifier ,hRowCurrent); } } } //if(bAlreadyDataRetrieved == FALSE) // prghRowsTemp[irow-1] = hRowCurrent; prghRowsTemp[irow-1] = hSlot; SysFreeString(strQualifier); strKey.Clear(); strKey.Unbind(); strQualifier = Wmioledb_SysAllocString(NULL); } if(SUCCEEDED(hr)) { cRowsTmp = irow - 1; //Irow will be +1 because of For Loop //===================================================================== // Through fetching many rows of data // // Allocate row handles for client. Note that we need to use IMalloc // for this. Should only malloc cRowsTmp, instead of ulMax. // Should malloc ulMax, since client will assume it's that big. //===================================================================== if ( *prghRows == NULL && cRowsTmp ) { try { *prghRows = (HROW *) g_pIMalloc->Alloc( cRowsTmp * sizeof( HROW )); } catch(...) { if(*prghRows) { g_pIMalloc->Free(prghRows); } throw; } bHRowsAllocated = TRUE; memset(*prghRows,0,cRowsTmp * sizeof( HROW )); } if ( *prghRows == NULL && cRowsTmp ) { hr = E_OUTOFMEMORY ; } else { //===================================================================== // Fill in the status information: Length, IsNull. May be able to wait // until first call to GetData, but have to do it sometime. // // Suggest keeping an array of structs of accessor info. One element is // whether accessor requires any status info or length info. // // Then we could skip this whole section. // // Added check for cRowsTmp to MarkRows call. Don't want to call if // cRowsTmp==0. // (Range passed to MarkRows is inclusive, so can't specify marking 0 rows.) // // Note that SetSlots is a CBitArray member function -- not an IBuffer function. // // Added row-wise reference counts and cursor-wise reference counts. // // Set row handles, fix data length field and compute data status field. //======================================================================= pRowset->m_cRows = cRowsTmp; // set the first position if it is zero if(lFetchPos == 0) { lFetchPos = 1; } for (ih =0; ih < (ULONG) pRowset->m_cRows; ih++) { //============================================================================= // Increment the rows-read count, // then store it as the bookmark in the very first DWORD of the row. //============================================================================= prowbuff = pRowset->GetRowBuff( prghRowsTemp[ih], TRUE ); //======================================================================================= // Insert the bookmark and its row number (from 1...n) into a hash table. // This allows us to quickly determine the presence of a row in mem, given the bookmark. // The bookmark is contained in the row buffer, at the very beginning. // Bookmark is the row number within the entire result set [1...num_rows_read]. // This was a new Bookmark, not in memory, // so return to user (in *prghRows) the hRow we stored. //======================================================================================= prowbuff->ulRefCount++; pRowset->m_ulRowRefCount++; (*prghRows)[ih] = prghRowsTemp[ih]; // (HROW) ( irow ); pRowset->m_hRowLastFetched = prghRowsTemp[ih]; // if bookmark property is true then initialize the bookmark if(pRowset->m_ulProps & BOOKMARKPROP) { if(ih != 0) { lFetchPos = (pRowset->m_FetchDir == FETCHDIRFORWARD ) ? lFetchPos + 1 : lFetchPos -1; } prowbuff->dwBmk = lFetchPos; prowbuff->cbBmk = BOOKMARKSIZE; pRowset->m_lLastFetchPos = lFetchPos; // Add bookmark to the hashtable pRowset->m_pHashTblBkmark->InsertFindBmk(FALSE,prghRowsTemp[ih],prowbuff->cbBmk,(BYTE *)&(prowbuff->dwBmk),(HROW *)&hSlot); } } // for loop } // else for memory allocation for HROWS } // if(succeeded(hr)) if(SUCCEEDED(hr)) { *pcRowsObtained = cRowsTmp; } //=================================================== // set return value if MAX_ROWS is exceeded //=================================================== if( hr == S_OK && bMaxRowsExceed == TRUE) { hr = DB_S_ROWLIMITEXCEEDED; } } // else for some basic parameter checking } // if(Succeeded(hr)) after setting the resetting offset } // else after checking for MAX rows limit } // if(cRows != 0) //============================================== // free the temporary memory allocated //============================================== if(FAILED(hr)) { // for(irow = irowFirst ; irow <= hRowTemp ; irow++) for (ih =0; ih < (ULONG) cRowsTmp; ih++) { if(prghRowsTemp[ih] != 0) { if(pRowset->m_bIsChildRs == FALSE) { pRowset->m_InstMgr->DeleteInstanceFromList(prghRowsTemp[ih]); } else { pRowset->m_pChapterMgr->DeleteHRow(prghRowsTemp[ih]); } } } if(pcRowsObtained) { *pcRowsObtained = 0; } // if HROWS for output parameter is allcated by this method // then release them if(prghRows && bHRowsAllocated == TRUE) { g_pIMalloc->Free(prghRows); prghRows = NULL; } else if(prghRows) { *prghRows = NULL; } if(pcRowsObtained) { *pcRowsObtained = 0; } if(strQualifier != NULL) { SysFreeString(strQualifier); } } //============================================== // free the temporary memory allocated //============================================== if(prghRowsTemp) { g_pIMalloc->Free(prghRowsTemp); prghRowsTemp = NULL; } // reset the starting position to the original position if(lRowOffset && (FAILED(hr) || (hr != S_OK && cRowsTmp == 0))) { pRowset->ResetRowsetToNewPosition(lRowOffset * (-1),pInst); } return hr; }