Creates and initializes a new row.
HRESULT InsertRow ( HCHAPTER hChapter, HACCESSOR hAccessor, void *pData, HROW *phRow);
Parameters
If hAccessor is a null accessor (that is, an accessor for which cBindings in IAccessor::CreateAccessor was zero), pData is ignored and the rows are initialized as specified in the Comments. Thus, the role of a null accessor is to construct a default row; it is a convenient way for a consumer to obtain a handle for a new row without having to set any values in that row initially. Passing an accessor with all columns set to DB_S_IGNORE is equivalent to passing a null accessor.
Note Passing in a null pointer for phRow or releasing the row handle returned in *phRow does not release the row until the change is transmitted to the data store. If DBPROP_CANHOLDROWS is VARIANT_FALSE and the rowset is in deferred update mode, then, in addition to freeing any reference counts on the row handle, the consumer must call IRowsetUpdate::Update in order to transmit the pending change to the data store before attempting to insert or retrieve any additional rows.
Return Code
Note The spec, as of 2.1, does not require this return code if the corresponding bit is not set.
The provider does not allow a rowset containing more than DBPROP_MAXROWS rows, and the insert would cause the rowset to exceed this limit.
Comments
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 applicable reasons listed in the corresponding DBBINDSTATUS values in IAccessor::CreateAccessor:
E_NOINTERFACE
DB_E_BADBINDINFO
DB_E_BADORDINAL
DB_E_BADSTORAGEFLAGS
DB_E_UNSUPPORTEDCONVERSION
IRowsetChange::InsertRow creates a new row and initializes its columns. If phRow is not a null pointer, it then returns the handle of this row to the consumer and sets its reference count to one. In delayed update mode, the row is created locally to the rowset and is transmitted to the data store only when IRowsetUpdate::Update is called. In immediate update mode, the row is immediately transmitted to the data store. For more information, see "Changing Data" in Chapter 5: Updating Data in Rowsets.
To the consumer, newly inserted rows are almost indistinguishable from other rows. For example, they can be deleted with IRowsetChange::DeleteRows and updated with IRowsetChange::SetData. However, methods that fetch rows might not be able to return them. Furthermore, they might not contain the correct values for computed columns, including bookmark columns on some providers. For more information, see "Visibility of Pending Changes" and "Visibility of Transmitted Changes" in Chapter 5: Updating Data in Rowsets. For information about where rows are inserted in the rowset, see "Position of Inserted Rows," also in Chapter 5.
The DBPROP_COLUMNRESTRICT and DBPROP_ROWRESTRICT properties affect how security is enforced and how security errors are returned. If DBPROP_COLUMNRESTRICT is VARIANT_TRUE, the consumer will not have write permission on at least one column. If the consumer attempts to write to these columns, IRowsetChange::InsertRow returns a column status of DBSTATUS_E_PERMISSIONDENIED and a return code of DB_S_ERRORSOCCURRED. If the DBPROP_ROWRESTRICT property is VARIANT_TRUE, the consumer might not have permission to insert some rows. If the consumer attempts to insert one of these rows, IRowsetChange::InsertRow returns a code of DB_SEC_E_PERMISSIONDENIED and no new row is created.
When a row is created, initialization proceeds in an orderly fashion. Conceptually, initialization consists of the following sequence of events.
Note This sequence is not intended to specify how providers must implement initialization.
If the column status is DBSTATUS_E_UNAVAILABLE, the consumer can still send this value to the data store to use the default. In this case, the default is available after the insertion is transmitted to the data store. To see the default, the consumer must call IRowsetRefresh::GetLastVisibleData or IRowsetRefresh::RefreshVisibleData. However, if there is no default for the column and it is non-nullable, this will cause a schema violation.
The provider is not required to compute the value of computed columns. If the provider does not compute the value of these columns but lets the data store do so, the computed value is not available until after the change is transmitted to the data store—that is, after IRowsetChange::InsertRow is called in immediate update mode or after IRowsetUpdate::Update if IRowsetChange::InsertRow is called in delayed update mode. To retrieve the computed value, the consumer calls RefreshVisibleData or GetLastVisibleData in IRowsetRefresh. Note that bookmark columns are often computed—for example, when the bookmark is the primary key or is a ROWID assigned by the data store.
Domain and schema validation is enforced as it is with IRowsetChange::SetData.
If IRowsetChange::InsertRow returns an error, it does not create a new row.
When setting rowset column data values from a consumer's storage object, the provider is responsible for releasing the storage object. When the provider has finished using the consumer's storage object, it calls IUnknown::Release to release the pointer. If the consumer wants to ensure access to its storage object after IRowsetChange::InsertRow returns, it must call IUnknown::AddRef on the pointer before calling IRowsetChange::InsertRow.
It is the consumer's responsibility to release VARIANTs stored in *pData. The consumer should call the COM method VariantClear when a VARIANT is no longer needed.
The use of null accessors is not recommended because some providers may not be able to determine default values and may not be able to identify a row inserted with all default values.
Here is an example of how one might write a projection-join to a temporary file:
#include <oledb.h> #include <stddef.h> int main() { IRowset * pLeftRowset; IRowset * pRightRowset; IAccessor * pLeftRowsetAcc; IAccessor * pRightRowsetAcc; IAccessor * pJoinRowsetAcc; IRowsetChange * pJoinRowsetNew; ULONG cSortedRows; HROW rghLeftRows [500]; HROW rghRightRows [500]; //... //< Sort and prepare the rows > //.. struct join { long * pl; double * pd; short * pi; }; static DBBINDING LeftBindings [1] = { { 1, offsetof (join, pl), 0, // No length binding 0, // No status binding NULL, // No TypeInfo NULL, // No object NULL, // No extensions DBPART_VALUE, DBMEMOWNER_PROVIDEROWNED, DBPARAMIO_NOTPARAM, sizeof (void*), 0, DBTYPE_I4 | DBTYPE_BYREF, 0, // No precision 0 // No scale } }; static DBBINDING RightBindings [2]= { { 1, offsetof (join, pd), 0, // No length binding 0, // No status binding NULL, // No TypeInfo NULL, // No object NULL, // No extensions DBPART_VALUE, DBMEMOWNER_PROVIDEROWNED, DBPARAMIO_NOTPARAM, sizeof (void*), 0, DBTYPE_R8 | DBTYPE_BYREF, 0, // No precision 0 // No scale }, { 2, offsetof (join, pi), 0, // No length binding 0, // No status binding NULL, // No TypeInfo NULL, // No object NULL, // No extensions DBPART_VALUE, DBMEMOWNER_PROVIDEROWNED, DBPARAMIO_NOTPARAM, sizeof (void*), 0, DBTYPE_I2 | DBTYPE_BYREF, 0, // No precision 0 // No scale } }; static DBBINDING JoinBindings [3] = { { 1, offsetof (join, pl), 0, // No length binding 0, // No status binding NULL, // No TypeInfo NULL, // No object NULL, // No extensions DBPART_VALUE, DBMEMOWNER_PROVIDEROWNED, DBPARAMIO_NOTPARAM, sizeof (void*), 0, DBTYPE_I4 | DBTYPE_BYREF, 0, // No precision 0 // No scale }, { 2, offsetof (join, pd), 0, // No length binding 0, // No status binding NULL, // No TypeInfo NULL, // No object NULL, // No extensions DBPART_VALUE, DBMEMOWNER_PROVIDEROWNED, DBPARAMIO_NOTPARAM, sizeof (void*), 0, DBTYPE_R8 | DBTYPE_BYREF, 0, // No precision 0 // No scale }, { 3, offsetof (join, pi), 0, // No length binding 0, // No status binding NULL, // No TypeInfo NULL, // No object NULL, // No extensions DBPART_VALUE, DBMEMOWNER_PROVIDEROWNED, DBPARAMIO_NOTPARAM, sizeof (void*), 0, DBTYPE_I2 | DBTYPE_BYREF, 0, // No precision 0 // No scale } }; HACCESSOR hLeft; HACCESSOR hRight; HACCESSOR hJoin; join theJoin; pLeftRowsetAcc->CreateAccessor(DBACCESSOR_ROWDATA, 1, LeftBindings, 0, &hLeft, NULL); pRightRowsetAcc->CreateAccessor(DBACCESSOR_ROWDATA, 2, RightBindings, 0, &hRight, NULL); pJoinRowsetAcc->CreateAccessor(DBACCESSOR_ROWDATA, 3, JoinBindings, 0, &hJoin, NULL); for (ULONG j = 0; j < cSortedRows; j++) { pLeftRowset->GetData(rghLeftRows[j], hLeft, &theJoin); pRightRowset->GetData(rghRightRows[j], hRight, &theJoin); pJoinRowsetNew->InsertRow(NULL, hJoin, &theJoin, NULL); } ; };
IRowset::GetData | IRowsetChange::SetData | IRowsetUpdate::Undo | IRowsetUpdate::Update