IRowset::GetData

Retrieves data from the rowset's copy of the row.

HRESULT GetData (
   HROW            hRow,
   HACCESSOR   hAccessor,
   void *            pData);

Parameters

hRow

[in]
The handle of the row from which to get the data.

Caution   The consumer must ensure that hRow contains a valid row handle; the provider might not validate hRow before using it. The result of passing the handle of a deleted row is provider-specific, although the provider cannot terminate abnormally. For example, the provider might return DB_E_BADROWHANDLE, DB_E_DELETEDROW, or it might get data from a different row. The result of passing an invalid row handle in hRow is undefined.

hAccessor

[in]
The handle of the accessor to use. If hAccessor is the handle of a null accessor (cBindings in IAccessor::CreateAccessor was zero), then GetData does not get any data values.

Caution   The consumer must ensure that hAccessor contains a valid accessor handle; the provider might not validate hAccessor before using it. The result of passing an invalid accessor handle in hAccessor is undefined.

pData

[out]
A pointer to a buffer in which to return the data. The consumer allocates memory for this buffer. This pointer must be a valid pointer to a contiguous block of consumer-owned memory into which the data will be written.

Return Code

S_OK
The method succeeded. The status of all columns bound by the accessor is set to DBSTATUS_S_OK, DBSTATUS_S_ISNULL, or DBSTATUS_S_TRUNCATED.

DB_S_ERRORSOCCURRED
An error occurred while returning data for one or more columns, but data was successfully returned for at least one column. To determine the columns for which data was returned, the consumer checks the status values. For a list of status values that can be returned by this method, see "Status Values Used When Getting Data" in "Status" in Chapter 6.

E_FAIL
A provider-specific error occurred.

E_INVALIDARG
pData was a null pointer and the accessor was not a null accessor.

E_UNEXPECTED
ITransaction::Commit or ITransaction::Abort was called and the object is in a zombie state.

DB_E_BADACCESSORHANDLE
hAccessor was invalid. Providers are not required to check for this condition, because doing so might slow the method significantly.

DB_E_BADACCESSORTYPE
The specified accessor was not a row accessor.

DB_E_BADROWHANDLE
hRow was invalid. Providers are not required to check for this condition, because doing so might slow the method significantly.

DB_E_DELETEDROW
hRow referred to a pending delete row or a row for which a deletion had been transmitted to the data source. Providers are not required to check for this condition, because doing so might slow the method significantly.

DB_E_ERRORSOCCURRED
Errors occurred while returning data for all columns. To determine what errors occurred, the consumer checks the status values. For a list of status values that can be returned by this method, see "Status Values Used When Getting Data" in "Status" in Chapter 6.

If this method performs deferred accessor validation and that validation takes place before any data is transferred, it can also return any of the following return codes for the reasons listed in the corresponding DBBINDSTATUS values in IAccessor::CreateAccessor:

E_NOINTERFACE
DB_E_BADBINDINFO
DB_E_BADORDINAL
DB_E_BADSTORAGEFLAGS
DB_E_UNSUPPORTEDCONVERSION

Comments

This method makes no logical change to the state of the object.

A consumer calls GetData to retrieve data from rows that have been fetched by prior calls to methods such as GetNextRows. For a complete description of how GetData retrieves data, see "Getting Data" in Chapter 6.

A consumer can call GetData any number of times. In each call, it can pass a different accessor and the address of a different buffer. This means that the consumer can get as many copies of the data as it wants, and it can get data in different types if alternate conversions are available.

GetData does not enforce any security restrictions. The provider must not create a rowset that includes columns for which the consumer does not have read privileges, so GetData never encounters problems accessing the data for a column. The rowset can contain columns to which the consumer does not have write permission if DBPROP_COLUMNRESTRICT is VARIANT_TRUE. The methods that fetch rows must not return the handles of rows for which the consumer does not have read privileges, so GetData never encounters problems accessing a row. Such rows might exist if the DBPROP_ROWRESTRICT property is VARIANT_TRUE.

If GetData fails, the memory to which pData points is not freed but its contents are undefined. If, before GetData failed, the provider allocated any memory for return to the consumer, the provider frees this memory and does not return it to the consumer.

GetData must be reentrant during notifications. If the provider calls a method from IRowsetNotify in the consumer, the consumer must be able to call GetData while processing the notification method.

The following example shows how a reference accessor is used.

#include <oledb.h> 
#include <stddef.h>

IRowset *TheRowset;
IAccessor *TheRowsetAccessor;
HROW   hRow;

int main() {
 struct ExactlyTheSame {
  long l;
  double d;
  short  i;
 };
 HACCESSOR hRawAccess;

 static DBBINDING ExactBindings [3] = {
  {
   1,         // iOrdinal
   offsetof (ExactlyTheSame,l), // obValue
   0,         // No length binding
   0,         // No Status binding
   NULL,        // No TypeInfo
   NULL,        // No Object
   NULL,        // No Extensions
   DBPART_VALUE,
   DBMEMOWNER_PROVIDEROWNED,  // Ignored
   DBPARAMIO_NOTPARAM,
   sizeof (long),
   0,
   DBTYPE_I4,
   0,         // No Precision
   0          // No Scale
  },
  {
   2,         // iOrdinal
   offsetof (ExactlyTheSame, d), // obValue
   0,          // No length binding
   0,          // No Status binding
   NULL,         // No TypeInfo
   NULL,         // No Object
   NULL,         // No Extensions
   DBPART_VALUE,
   DBMEMOWNER_PROVIDEROWNED,   // Ignored
   DBPARAMIO_NOTPARAM,
   sizeof (double),
   0,
   DBTYPE_R8,
   0,          // No Precision
   0           // No Scale
  },
  {
   3,         // iOrdinal
   offsetof (ExactlyTheSame,i), // obValue
   0,         // No length binding
   0,         // No Status binding
   NULL,        // No TypeInfo
   NULL,        // No Object
   NULL,        // No Extensions
   DBPART_VALUE,
   DBMEMOWNER_PROVIDEROWNED,  // Ignored
   DBPARAMIO_NOTPARAM,
   sizeof (short),
   0,
   DBTYPE_I2,
   0,         // No Precision
   0          // No Scale
  }
 };

 TheRowsetAccessor->CreateAccessor (DBACCESSOR_PASSBYREF, 3, ExactBindings, 0,
              &hRawAccess, NULL);

To read the column i of some row, the consumer should do the following:

short     value;
ExactlyTheSame *pRow;

TheRowset->GetData(hRow, hRawAccess, &pRow);

value = pRow->i;

The following example shows how provider-owned memory is used.

#include <oledb.h> 
#include <stddef.h>

IRowset *TheRowset;
IAccessor *TheRowsetAccessor;
HROW   hRow;

int main() {
 struct IndirectlySimilar {
  long * pl;
  double * pd;
  short * pi;
 };
 HACCESSOR hFastAccess;

 static DBBINDING IndirectBindings [3] = {
  {
   1,            // iOrdinal
   offsetof (IndirectlySimilar, pl), // obValue
   0,            // No length binding
   0,            // No Status binding
   NULL,           // No TypeInfo
   NULL,           // No Object
   NULL,           // No Extensions
   DBPART_VALUE,
   DBMEMOWNER_PROVIDEROWNED,
   DBPARAMIO_NOTPARAM,
   sizeof (long*),
   0,
   DBTYPE_BYREF|DBTYPE_I4,
   0,            // No Precision
   0           // No Scale
  },
  {
   2,            // iOrdinal
   offsetof (IndirectlySimilar, pd), // obValue
   0,            // No length binding
   0,            // No Status binding
   NULL,           // No TypeInfo
   NULL,           // No Object
   NULL,           // No Extensions
   DBPART_VALUE,
   DBMEMOWNER_PROVIDEROWNED,
   DBPARAMIO_NOTPARAM,
   sizeof (double*),
   0,
   DBTYPE_BYREF|DBTYPE_R8,
   0,            // No Precision
   0           // No Scale
  },
  {
   3,           // iOrdinal
   offsetof (IndirectlySimilar,pi), // obValue
   0,           // No length binding
   0,           // No Status binding
   NULL,          // No TypeInfo
   NULL,          // No Object
   NULL,          // No Extensions
   DBPART_VALUE,
   DBMEMOWNER_PROVIDEROWNED,
   DBPARAMIO_NOTPARAM,
   sizeof(short*),
   0,
   DBTYPE_BYREF|DBTYPE_I2,
   0,           // No Precision
   0            // No Scale
  }
 };

 TheRowsetAccessor->CreateAccessor (DBACCESSOR_ROWDATA, 3, IndirectBindings, 0,
              &hFastAccess, NULL );

To read the column i of some row, the consumer should do the following:

short        value;
IndirectlySimilar   rowPs;

TheRowset->GetData (hRow, hFastAccess, &rowPs);

if (rowPs.pi)    // Avoid null pointers
 value = *(rowPs.pi);

See Also

IRowset::GetNextRows, IRowsetChange::SetData