Getting Data

To get data, such as with IRowset::GetData for rowset data or ICommand::Execute for output parameter data, the consumer performs the following actions:

  1. Creates an accessor to bind the columns or output parameters as desired.

  2. Allocates a buffer to hold the data returned by the provider.

  3. Calls a method that gets data and passes the handle to the accessor and a pointer to the buffer.

For each column or output parameter specified in the accessor, the provider performs the actions in the following procedure. This procedure assumes that the consumer has bound the value, length, and status for each column or output parameter. If any of these are not bound, the procedure is the same except that the provider does not return the unbound part.

Note  If the accessor is a reference accessor, the provider does not follow this procedure but returns a pointer to the provider's memory that contains the data. For more information, see "Reference Accessors" earlier in this chapter.

  1. Validates the accessor against the metadata if it has not already done so.

    The provider can validate the entire accessor before returning any data or on a binding-by-binding basis while returning data. If validation fails in the former case, the provider produces the appropriate return code and does not return any data. If it fails in the latter case, the provider sets the status of the column or output parameter to DBSTATUS_E_BADACCESSOR and proceeds to the next column or output parameter.

  2. Checks if the data is NULL.

    If it is, the provider sets the status to DBSTATUS_S_ISNULL or VT_NULL, sets the length to zero, ignores the value, and proceeds to the next column or output parameter. The address at which the status value is placed is calculated from the buffer address passed to the method and the obStatus element of the binding. A variant whose type is VT_NULL is different from a column status of DBSTATUS_S_ISNULL. Providers supporting variants, as well as consumers binding to variants, must be prepared to handle either type of NULL. However, if DBSTATUS_S_ISNULL is specified in the status binding, the contents of the value binding, regardless of type, are undefined.

  3. Converts the data to the type specified by the wType element of the binding. If an error occurs while converting the data, the provider sets the status accordingly and proceeds to the next column or output parameter.

    For a list of status values that describe conversion errors, see "Status Values Used When Getting Data" in "Status," earlier in this chapter. For more information about converting data, see "Data Type Conversion Rules" in Appendix A.

  4. Sets the length. The address at which the length value is placed is calculated from the buffer address passed to the method and the obLength element of the binding.
    • Variable-length data types—The length of variable-length data types is the length of the untruncated data in bytes, not counting the null-termination character for strings.

    • Fixed-length data types—The length of fixed-length data types is the size of the data type. If wType is DBTYPE_IUNKNOWN or DBTYPE_IDISPATCH, the length is sizeof(IUnknown*), not the size of the object to which the interface pointer points, and if wType is DBTYPE_BSTR, the length is sizeof(BSTR), not the length of the string itself.

    • DBTYPE_BYREF—DBTYPE_BYREF does not affect the length value. For example, if wType is DBTYPE_BYREF | DBTYPE_STR, the length is the length in bytes of the string, not the length of the pointer.

    • DBTYPE_VECTOR, DBTYPE_ARRAY—If the type indicator is joined in a logical OR with DBTYPE_ARRAY or DBTYPE_VECTOR, the length is zero.
  5. Sets the data value to the converted data. The address at which the data value is placed is calculated from the buffer address passed to the method and the obValue element of the binding.
    • Variable-length data types—If the length in bytes of the converted, variable-length data is greater than cbMaxLen bytes, the provider truncates the data to cbMaxLen bytes before placing it in the consumer buffer and sets the status to DBSTATUS_S_TRUNCATED. Otherwise, the provider places the data in the consumer buffer without truncating it.

    • Fixed-length data types—The provider places the converted, fixed-length data in the consumer's buffer. The provider ignores cbMaxLen; it does not truncate the data before placing it in the consumer's buffer.

      If the type indicator is DBTYPE_IUNKNOWN or DBTYPE_IDISPATCH, the data value is a pointer to an interface on the OLE object, not the object itself. For more information, see Chapter 7, "BLOBs and OLE Objects."

      If the type indicator is DBTYPE_BSTR, the provider places the converted data in a BSTR and places a pointer to the BSTR in the consumer's buffer. The provider ignores cbMaxLen; it does not truncate the data before placing it in the consumer's buffer. For information about how the BSTR is allocated and freed, see "Memory Management" earlier in this chapter.

    • DBTYPE_BYREF, DBTYPE_VECTOR, DBTYPE_ARRAY—For DBTYPE_BYREF, the provider places the converted data in separately allocated memory and places a pointer to this memory in the consumer's buffer. For DBTYPE_VECTOR, the provider places the converted data in an array and places the count of array elements and a pointer to the array in a DBVECTOR structure in the consumer's buffer. For DBTYPE_ARRAY, the provider places the converted data in a SAFEARRAY and places a pointer to the SAFEARRAY in the consumer's buffer. In each case, the provider ignores cbMaxLen; that is, it does not truncate the data before placing it in the separate memory, array, or SAFEARRAY. For information about how the separate memory, array, or SAFEARRAY is allocated and freed, see "Memory Management" earlier in this chapter.
  6. Sets the status to DBSTATUS_S_OK if it hasn't already been set to another value.

If the provider encounters an error while returning a column or output parameter value, it sets the status value of that column or output parameter. The provider then continues to process the remaining columns or output parameters. After it has processed all columns or output parameters, it produces one of the following return codes.

The consumer checks the status values to determine the columns or output parameters for which data was successfully returned. If the consumer did not bind a status value for a column or output parameter and a method returns DB_S_ERRORSOCCURRED or DB_E_ERRORSOCCURRED, the consumer must assume that the column or output parameter value was not successfully returned.

The provider frees any memory it allocated for return to the consumer but did not return to the consumer due to an error. If the method fails completely, the contents of the consumer's buffer are undefined.