Share via


Retrieving Data from the Data Cache

IRowset::GetData enables consumers to retrieve data from the data cache. GetData uses the bindings in the accessor to determine how the data should be returned and what data should be returned to the consumer's buffer. Then, GetData converts the data in the cache to the type specified in the binding and transfers the converted data to the consumer. The source code for IRowset::GetData follows.

Example

// CImpIRowset::GetData -------------
//
// @mfunc Retrieves data from the rowset's cache
//
// @rdesc   Returns one of the following values:
//      @flag S_OK                   | Method Succeeded
//      @flag DB_S_ERRORSOCCURED     | Could not coerce a column value
//      @flag DB_E_BADACCESSORHANDLE | Invalid Accessor given
//      @flag DB_E_BADROWHANDLE      | Invalid row handle given
//      @flag E_INVALIDARG           | pData was NULL
//      @flag OTHER                  | Other HRESULTs returned by called functions
//
STDMETHODIMP CImpIRowset::GetData
    (
    HROW        hRow,       //@parm IN | Row Handle
    HACCESSOR   hAccessor,  //@parm IN | Accessor to use
    void       *pData       //@parm OUT | Pointer to buffer where data should go.
    )
{
    PACCESSOR      pAccessor;
    DBORDINAL      cCols;
   DBORDINAL      cBind;
    ROWBUFF         *pRowBuff;
    COLUMNDATA      *pColumnData;
    DBBINDING      *pBinding;
    DBCOUNTITEM      cBindings;
    DBORDINAL      cErrorCount;
    DBTYPE         dwSrcType;
    DBTYPE         dwDstType;
    void         *pSrc;
    void         *pDst;
    DBBYTEOFFSET   ulSrcLength;
    DBLENGTH*      pulDstLength;
    DBLENGTH      cbDstMaxLength;
    ULONG         dwSrcStatus;
    ULONG         *pdwDstStatus;
    DWORD         dwPart;
    HRESULT         hr;

   DBCOLUMNINFO *   rgdbcolumninfo = NULL;

    // Coerce data for row 'hRow', according to hAccessor.
    // Put in location 'pData'.  Offsets and types are in hAccessor's bindings.
    //
   // Return S_OK if all columns retrieved with successful status
    // Return DB_S_ERRORSOCCURED on failure to retrieve one or more column values
    // Return DB_E_ERRORSOCCURED on failure to retrieve all column values

    // GetItemOfExtBuffer is basically operator[].
    // It takes an index (or handle) (referenced from 1...n),
    // and a ptr for where to write the data.
    //
    // It holds ptrs to a variable-length ACCESSOR struct.
    // So we get the ACCESSOR ptr for the client's accessor handle.

    assert( m_pObj->m_pextbufferAccessor );
    m_pObj->m_pextbufferAccessor->GetItemOfExtBuffer(hAccessor, &pAccessor);
    if( !pAccessor )
        return DB_E_BADACCESSORHANDLE;

    assert( pAccessor );
    cBindings = pAccessor->cBindings;
    pBinding  = pAccessor->rgBindings;

    // IsSlotSet returns S_OK    if row is marked.
    //                   S_FALSE if row is not marked.
    // The "mark" means that there is data present in the row.
    // Rows are [1...n], slot marks are [0...n-1].
    if (m_pObj->m_prowbitsIBuffer->IsSlotSet( (ULONG) hRow ) != S_OK)
        return ResultFromScode( DB_E_BADROWHANDLE );

   // Ensure a place to put data, unless the accessor is the null accessor then
    // a NULL pData is okay.
    if ( pData == NULL && cBindings != 0 )
        return ResultFromScode( E_INVALIDARG );

   // Check to see if we have a DC
   if( !g_pIDataConvert)
      return (E_FAIL);

    // Internal error for a 0 reference count on this row,
    // since we depend on the slot-set stuff.
    pRowBuff = m_pObj->GetRowBuff( (DBCOUNTITEM) hRow, TRUE );
    assert( pRowBuff->ulRefCount );

   // Check for the Deleted Row
   if ( m_pObj->m_pFileio->IsDeleted( (DBBKMARK) pRowBuff->pbBmk ) == S_OK )
        return ResultFromScode( DB_E_DELETEDROW );

    cErrorCount = 0;
   rgdbcolumninfo = m_pObj->m_pFileio->GetColInfo();
    for (cBind=0; cBind < cBindings; cBind++)
   {
      cCols = pBinding[cBind].iOrdinal;

        // make sure column number is in range
        if ( !(0 < cCols && cCols <= m_pObj->m_cCols) )
            return ResultFromScode( DB_E_BADORDINAL );

        pColumnData    = m_pObj->m_pFileio->GetColumnData(cCols, pRowBuff);

        dwSrcType      = rgdbcolumninfo[cCols].wType;
        pSrc           = &(pColumnData->bData);
        ulSrcLength    = pColumnData->dwLength;
        dwSrcStatus    = pColumnData->dwStatus;
        cbDstMaxLength = pBinding[cBind].cbMaxLen;
        dwDstType      = pBinding[cBind].wType;
        dwPart         = pBinding[cBind].dwPart;

        pDst           = dwPart & DBPART_VALUE ? ((BYTE *) pData + pBinding[cBind].obValue) : NULL;
        pulDstLength   = dwPart & DBPART_LENGTH ? (DBLENGTH *) ((BYTE*) pData + pBinding[cBind].obLength) : NULL;
        pdwDstStatus   = dwPart & DBPART_STATUS ? (ULONG *) ((BYTE*) pData + pBinding[cBind].obStatus) : NULL;

        hr = g_pIDataConvert->DataConvert(
                dwSrcType,
                dwDstType,
                ulSrcLength,
                pulDstLength,
                pSrc,
                pDst,
                cbDstMaxLength,
                dwSrcStatus,
                pdwDstStatus,
                pBinding[cBind].bPrecision,   // bPrecision for conversion to DBNUMERIC
            pBinding[cBind].bScale,      // bScale for conversion to DBNUMERIC
            DBDATACONVERT_DEFAULT);
        
      // rounding or truncation or can't coerce
      if (hr != S_OK)
            cErrorCount++;
   }

    // We report any lossy conversions with a special status.
    // Note that DB_S_ERRORSOCCURED is a success, rather than failure.
   return cErrorCount ? ( cErrorCount < cBindings ) ? 
      ( DB_S_ERRORSOCCURRED ) : ( DB_E_ERRORSOCCURRED ) : ( S_OK );
}

See Also

Tasks

Writing an OLE DB Provider: An Introduction