IAccessor::CreateAccessor

CreateAccessor creates an accessor from a set of bindings.

HRESULT CreateAccessor (
   DBACCESSORFLAGS      dwAccessorFlags,
   ULONG                     cBindings,
   const DBBINDING            rgBindings[],
   ULONG                     cbRowSize,
   HACCESSOR *               phAccessor,
   DBBINDSTATUS            rgStatus[]);

Parameters

dwAccessorFlags

[in]
A bitmask that describes the properties of the accessor and how it is to be used. These flags have the following meanings.

Value Description
DBACCESSOR_
INVALID
This flag is used by GetBindings to indicate that the method failed.
DBACCESSOR_
PASSBYREF
The accessor is a reference accessor.

The value passed in the consumer buffer is a pointer to the passer's internal buffer. This pointer need not point to the start of the internal buffer, as long as the relative offsets of all elements of the buffer align with the offsets specified in the accessor. The passee must know the internal structure of the passer's buffer in order to read information from it. The passee must not free the buffer at the pointer, nor may it write to this buffer.

For row accessors, this buffer is the rowset's copy of the row. The consumer reads information directly from this copy of the row at a later point in time, so the provider must guarantee that the pointer remains valid.

For parameter accessors, this buffer is the consumer's buffer. The provider reads data from this buffer only when ICommand::Execute is called, so the pointer is not required to remain valid after Execute returns.

Support for this flag is optional. A consumer determines whether a provider supports this bit by calling IDBProperties::GetProperties for the DBPROP_BYREFACCESSORS property.

When this flag is used, the dwMemOwner in the DBBINDING structure is ignored. If the accessor is used for row data, the accessor refers to the provider's memory; the consumer must not write to or free this memory. If the accessor is used for input parameters, the provider copies the row of data without assuming ownership.

It is an error to specify an output or input/output parameter in a reference accessor.

For more information, see "Reference Accessors" in Chapter 6.

DBACCESSOR_
ROWDATA
The accessor is a row accessor and describes bindings to columns in the rowset.

An accessor may be a row accessor, a parameter accessor, or both.

DBACCESSOR_
PARAMETERDATA
The accessor is a parameter accessor and describes bindings to parameters in the command text. In a parameter accessor, it is an error to bind an input or an input/output parameter more than once.
DBACCESSOR_
OPTIMIZED
The row accessor is to be optimized. This hint may affect how a provider structures its internal buffers. A particular column can be bound by only one optimized accessor. The column can also be bound by other, nonoptimized accessors, but the types specified in the nonoptimized accessors must be convertable from the type in the optimized accessor. All optimized accessors must be created before the first row is fetched with IRowset::GetNextRows, IRowsetLocate::GetRowsAt, IRowsetLocate::GetRowsByBookmark, or IRowsetScroll::GetRowsAtRatio.

This flag is ignored for parameter accessors.


cBindings

[in]
The number of bindings in the accessor.

If cBindings is zero, CreateAccessor creates a null accessor. Null accessors are used only by IRowsetChange::InsertRow to create a new row in which each column is set to its default value, NULL, or a status of DBSTATUS_E_UNAVAILABLE. Providers that support InsertRow must support the creation of null accessors. For more information, see InsertRow.

rgBindings

[in]
An array of DBBINDING structures. For more information, see "DBBINDING Structures" in Chapter 6.

cbRowSize

[in]
The numer of bytes allocated for a single set of parameters or criteria values in the consumer's buffer.

cbRowSize is used by ICommand::Execute to process multiple sets of parameters, and by IViewFilter::GetFilter and IViewFilter::SetFilter to get and set multiple OR' conditions in criteria. In both cases, a single accessor may describe multiple sets of values. cbRowSize is generally the size of the structure that contains a single set of parameter or critieria values and is used as the offset to the start of the next set of values within the array of structures. For example, if cParamSets is greater than 1 in the DBPARAMS structure passed to Execute, the provider assumes that the pData element of this structure points to an array of structures containing parameter values, each cbRowSize bytes in size. Similarly, if cRows is greater than 1 in SetFilter, the provider assumes that the pCriteriaData argument points to an array of structures containing criteria values, each cbRowSize bytes in size.

cbRowSize must be large enough to contain the structure defined by the bindings in rgBindings. The provider is not required to verify this, although it may.

cbRowSize is not used when fetching rowset data.

phAccessor

[out]
A pointer to memory in which to return the handle of the created accessor. If CreateAccessor fails, it must attempt to set *phAccessor to a null handle.

rgStatus

[out]
An array of cBindings DBBINDSTATUS values in which CreateAccessor returns the status of each binding; that is, whether it was successfully validated or not. If rgStatus is a null pointer, no bind status values are returned. The consumer allocates and owns the memory for this array. The bind status values are returned for the following reasons.

Value Description
DBBINDSTATUS_OK No errors were found in the binding. Because accessor validation can be deferred, a status of DBBINDSTATUS_OK does not necessarily mean that the binding was successfully validated.
DBBINDSTATUS_
BADORDINAL
A parameter ordinal was zero in a parameter accessor.

If the accessor is validated against the metadata when CreateAccessor is called, DBBINDSTATUS_BADORDINAL can be returned for the following reasons:

  • In a row accessor, a column ordinal in a binding was outside the range of available columns on the rowset.

  • In a parameter accessor, a parameter ordinal was greater than the number of parameters in the command text.

These reasons cause a status value of DBSTATUS_E_BADACCESSOR to be returned if the accessor is validated when used.

Some providers may support binding more parameters than the number of parameters in the command text, and such providers do not return DBBINDSTATUS_BADORDINAL in this case.

DBBINDSTATUS_
UNSUPPORTED
CONVERSION
If the accessor is validated against the metadata when CreateAccessor is called, DBBINDSTATUS_UNSUPPORTEDCONVERSION can be returned for the following reason:
  • The specified conversion was not supported by the provider. For a list of conversions the accessor must support, see "Data Type Conversion" in Chapter 10.

  • The consumer attempted to convert a column to a storage object (ISequentialStream, IStorage, IStream, ILockBytes) and the particular conversion is not supported by the provider.

These reasons cause a status value of DBSTATUS_E_BADACCESSOR to be returned if the accessor is validated when used.

DBBINDSTATUS_
BADBINDINFO
dwPart in a binding was not one of the following:

DBPART_VALUE
DBPART_LENGTH
DBPART_STATUS

eParamIO in a binding in a parameter accessor was not one of the following:

DBPARAMIO_INPUT
DBPARAMIO_OUTPUT
DBPARAMIO_INPUT | DBPARAMIO_OUTPUT

A row accessor was optimized and a column ordinal in a binding was already used in another optimized accessor.

In a parameter accessor, two or more bindings contained the same ordinal for an input or input/output parameter.

wType in a binding was DBTYPE_EMPTY or DBTYPE_NULL.

wType in a binding was one of the following:

DBTYPE_BYREF | DBTYPE _EMPTY,
DBTYPE_BYREF | DBTYPE_NULL, or
DBTYPE_BYREF | DBTYPE_RESERVED.

wType in a binding was used with more than one of the following mutually exclusive type indicators: DBTYPE_BYREF, DBTYPE_ARRAY, or DBTYPE_VECTOR.

wType in a binding was DBTYPE_IUNKNOWN, and pObject in the same binding was a null pointer.

Provider-owned memory was specified for a nonpointer type in a nonreference row accessor.

Provider-owned memory was specified for a column and the provider does not support binding to provider-owned memory for this column.

Provider-owned memory was specified for a column for which IColumnsInfo::GetColumnInfo returned DBCOLUMNFLAGS_ISLONG.

In a nonreference parameter accessor, a binding specified provider-owned memory.

An output or input/output parameter was specified in a parameter reference accessor.

dwFlags in a binding was set to DBBINDFLAG_HTML, and wType for the same binding was not a string value.

If the accessor is validated against the metadata when CreateAccessor is called, DBBINDSTATUS_BADBINDINFO can be returned for the following reasons:

  • A row accessor was not optimized, a column number in a binding specified a column that was already used in an optimized accessor, and the provider did not support a conversion from the type specified in the optimized accessor for the column to the type specified in wType.

  • In a parameter accessor, eParamIO in a binding specified the incorrect I/O type for the parameter. Some providers cannot determine parameter I/O types and never return DBBINDSTATUS_BADBINDINFO in this case.

  • In a reference accessor, the value specified for dwPart, obValue, cbMaxLen, or wType in a binding did not match the format of the corresponding element in the rowset's copy of the row.

  • In a nonreference accessor, a binding specified provider-owned memory, wType was X | DBTYPE_BYREF, and the data type of the corresponding element of the rowset's copy of the row was not X or X | DBTYPE_BYREF.

  • In a nonreference accessor, a binding specified provider-owned memory, wType was DBTYPE_BSTR, and the data type of the corresponding element of the rowset's copy of the row was not DBTYPE_BSTR.

  • The accessor was used for passing key column values in IRowsetIndex::Seek or IRowsetIndex::SetRange, and the order in which the key columns were bound did not match the order in which they were returned in IColumnsInfo::GetColumnInfo.

  • The accessor was used for passing key column values in Seek or SetRange, and a less significant key column was bound without binding all more significant key columns.

  • The accessor was used for passing key column values in Seek or SetRange, and a non-key column was bound before the last bound key column.

  • These reasons cause a status value of DBSTATUS_E_BADACCESSOR to be returned if the accessor is validated when used.
DBBINDSTATUS_
BADSTORAGE
FLAGS
dwFlags, in the DBOBJECT structure pointed to by a binding, specified invalid storage flags.

If the accessor is validated against the metadata when CreateAccessor is called, DBBINDSTATUS_BADSTORAGEFLAGS can be returned for the following reason:

  • dwFlags, in the DBOBJECT structure pointed to by a binding, specified a valid storage flag that was not supported by the object.

These reasons cause a status value of DBSTATUS_E_BADACCESSOR to be returned if the accessor is validated when used.

DBBINDSTATUS_
NOINTERFACE
If the accessor is validated against the metadata when CreateAccessor is called, DBBINDSTATUS_NOINTERFACE can be returned for the following reasons:
  • The provider did not support the storage interface specified in iid in the DBOBJECT structure pointed to by a binding in the accessor.

  • The OLE object in a column or parameter did not support the interface specified in iid in the DBOBJECT structure pointed to by the corresponding binding in the accessor.

  • The provider supports only one open storage object at a time—that is, DBPROP_MULTIPLESTORAGEOBJECTS is VARIANT_FALSE—and wType in more than one binding was DBTYPE_IUNKNOWN.

These reasons cause a status value of DBSTATUS_E_BADACCESSOR to be returned if the accessor is validated when used.


Return Code

S_OK
The method succeeded. If rgStatus is not a null pointer, each element is set to DBBINDSTATUS_OK.

E_FAIL
A provider-specific error occurred.

E_INVALIDARG
phAccessor was a null pointer.

cBindings was not zero and rgBindings was a null pointer.

E_UNEXPECTED
ITransaction::Commit or ITransaction::Abort was called and the object is in a zombie state. This error can be returned only when the method is called on a rowset.

DB_E_BADACCESSORFLAGS
dwAccessorFlags was invalid.

The DBACCESSOR_PARAMETERDATA bit was set in dwAccessorFlags, and the provider does not support parameters.

Neither the DBACCESSOR_PARAMETERDATA bit nor the DBACCESSOR_ROWDATA bit was set in dwAccessorFlags.

A method that fetches rows (IRowset::GetNextRows, IRowsetLocate::GetRowsAt, IRowsetLocate::GetRowsByBookmark, or IRowsetScroll::GetRowsAtRatio) had already been called and the DBACCESSOR_OPTIMIZED bit in dwAccessorFlags was set.

The DBACCESSOR_ PARAMETERDATA bit was set and CreateAccessor was called on a rowset.

DB_E_BYREFACCESSORNOTSUPPORTED
dwAccessorFlags was DBACCESSOR_PASSBYREF and the value of the DBPROP_BYREFACCESSORS property is VARIANT_FALSE.

DB_E_ERRORSOCCURRED
Accessor validation failed. To determine which bindings failed, the consumer checks the values returned in rgStatus, at least one of which is not DBBINDSTATUS_OK.

DB_E_NOTREENTRANT
The provider called a method from IRowsetNotify in the consumer and the method has not yet returned.

DB_E_NULLACCESSORNOTSUPPORTED
cBindings was zero and the rowset does not support IRowsetChange::InsertRow, or CreateAccessor was called on a command.

Comments

For general information about accessors, see "Accessors" in Chapter 6.

CreateAccessor always checks all error conditions that do not require it to validate the accessor against the metadata. As a general rule, this means it checks the error conditions for all of the return codes except those that return DB_E_ERRORSOCCURRED. CreateAccessor may validate the accessor against the metadata for row accessors created on the rowset; it never validates the accessor against the metadata for row or parameter accessors created on the command. When CreateAccessor validates the accessor against the metadata, it validates each binding in the accessor, setting the appropriate DBBINDSTATUS values as it goes. If CreateAccessor fails in any way, it does not create the accessor and sets *phAccessor to a null handle.

If CreateAccessor does not validate the accessor against the metadata, then the validation is said to be delayed. CreateAccessor simply creates the accessor and validation is done by the first method that uses the accessor. If the accessor is found to be invalid, it remains in existence and can be used again.

If accessor validation is delayed, the provider determines whether the method validating the accessor validates it against the metadata before or during data transfer. If the method validates the accessor before transferring any data, it can return any of the return codes listed below for this purpose. If the method validates the accessor while transferring the data, it sets the status value of any column or parameter for which the accessor is invalid (within the context of the method) to DBSTATUS_E_BADACCESSOR and returns DB_S_ERRORSOCCURRED or DB_E_ERRORSOCCURRED. Whether the method continues processing other columns or parameters depends on both the method and the provider.

The following return codes are returned by methods that perform delayed accessor validation before transferring any data. The DBBINDSTATUS value to which each corresponds is also listed.

Return code DBBINDSTATUS value
E_NOINTERFACE DBBINDSTATUS_NOINTERFACE
DB_E_BADBINDINFO DBBINDSTATUS_BADBINDINFO
DB_E_BADORDINAL DBBINDSTATUS_BADORDINAL
DB_E_BADSTORAGEFLAGS DBBINDSTATUS_
BADSTORAGEFLAGS
DB_E_UNSUPPORTEDCONVERSION DBBINDSTATUS_
UNSUPPORTEDCONVERSION

Providers that do not support conversion of BLOB or non-BLOB data to a data structured storage interface should fail the accessor creation method with DB_E_ERRORSOCCURED and report DBBINDSTATUS_UNSUPPORTEDCONVERSION on the column specifying the incorrect binding.

See Also

IAccessor::GetBindings, IAccessor::ReleaseAccessor, IConvertType::CanConvert, IRowset::GetData, IRowsetChange::SetData