IRowSchemaChange::AddColumns

Creates or sets the values of one or more named columns of a row object. If the columns do not already exist, they are created.

Syntax

HRESULT AddColumns(
   DBORDINAL            cColumns,
   const DBCOLUMNINFO   rgNewColumnInfo[ ],
   DBCOLUMNACCESS       rgColumns[ ]
);

Parameters

  • cColumns
    [in] Count of columns specified in the rgNewColumnInfo array. If cColumns is zero, no columns are created or set.

  • rgNewColumnInfo
    [in] A consumer-allocated array of cColumns DBCOLUMNINFO structures that define the additional columns to be added to the row object. If cColumns is zero, rgNewColumnInfo is ignored. The order of columns in rgColumns must match the order of columns in rgNewColumnInfo.

    Note

    For information about DBCOLUMNINFO structures, see IColumnsInfo::GetColumnInfo.

    The following table lists special instructions for defining row columns using DBCOLUMNINFO.

    Element

    Instructions for row columns

    pwszName

    Ignored on input when creating columns with AddColumns.

    iOrdinal

    Ignored on input when creating columns with AddColumns.

    dwFlags

    A bitmask that describes consumer-specified row column characteristics. The DBCOLUMNFLAGS enumerated type specifies the bits in the bitmask, which are described in the reference entry for IColumnsInfo::GetColumnInfo. The following flag values may apply when creating row columns:

    • DBCOLUMNFLAGS_CACHEDEFERRED

    • DBCOLUMNFLAGS_ISFIXEDLENGTH

    • DBCOLUMNFLAGS_ISLONG

    • DBCOLUMNFLAGS_ISNULLABLE

    • DBCOLUMNFLAGS_ISROWVER

    • DBCOLUMNFLAGS_MAYBENULL

    • DBCOLUMNFLAGS_MAYDEFER

    • DBCOLUMNFLAGS_SCALEISNEGATIVE

    • DBCOLUMNFLAGS_WRITE

    • DBCOLUMNFLAGS_WRITEUNKNOWN

    ulColumnSize

    Minimum size required to store the consumer's largest data for this column. For fixed-length data types, this is the size of the data type in bytes. For variable-length data types, this is the maximum number of bytes (for DBTYPE_BYTES) or characters (for DBTYPE_STR or DBTYPE_WSTR). For more information, see the description of DBCOLUMNINFO in the reference entry for IColumnsInfo::GetColumnInfo.

    wType

    Requested DBTYPE data type for this column.

    bPrecision

    Maximum precision of the column.

    bScale

    Number of digits to the right of the decimal point.

    columnid

    Unique DBID used to name this row column. For example, if columns are named (eKind is DBKIND_NAME), uName.pwszName points to the column name.

  • rgColumns
    [in/out] An optional consumer-allocated array of cColumns DBCOLUMNACCESS structures.

    Note

    The DBCOLUMNACCESS structure is described in the reference entry for IRow::GetColumns.

    The order of columns in rgColumns must match the order of columns in rgNewColumnInfo. If rgColumns is a null pointer, new columns are created but no values are set (except for default values defined by the provider).

    For setting column values, the elements of each DBCOLUMNACCESS structure are used in the manner described in the following table.

    Element

    Description

    columnid

    This element is ignored by AddColumns. The column DBID is designated by the columnid element of the corresponding member of rgNewColumnInfo. (This is done so that consumers do not need to allocate two sets of DBIDs.)

    wType

    Identifies the type of the value pointed to by pData.

    pData

    Caller-allocated pointer to storage of the DBTYPE defined by wType. On input, the area pointed to contains the value of the column specified by the columnid element of rgNewColumnInfo. The caller must allocate and initialize the area of storage pointed to by pData. The provider should attempt to coerce the value from wType to the underlying value of the column. If wType is DBTYPE_VARIANT, the provider is responsible for allocating any variable-length storage pointed to by the VARIANT.

    cbMaxLen

    The maximum length of the caller-initialized memory pointed to by pData. The provider checks the length in bytes of variable-length data types against cbMaxLen. If the length is greater than cbMaxLen, this is an error and the provider sets the status to DBSTATUS_E_CANTCONVERTVALUE.

    bPrecision

    Indicates the precision of the value stored in *pData for data types requiring precision.

    bScale

    Indicates the scale of the value stored in *pData for data types requiring scale.

    dwStatus

    On input, dwStatus indicates whether pData or some other value should be used. All status values used in OLE DB for rowset columns apply to row columns. On input, if dwStatus is DBSTATUS_S_DEFAULT or DBSTATUS_S_IGNORE, the provider skips this column when setting data. On return, dwStatus indicates whether the field was successfully set. The following status values may apply when updating column values. Standard status values when setting data do apply in addition to those listed in the following table. For more information about Status, see Getting and Setting Data.)

    • DBSTATUS_S_OK The column value was set.

    • DBSTATUS_S_ALREADYEXISTS The column already exists on the row. The new column metadata was ignored.

      NoteNote
      DBSTATUS_S_ALREADYEXISTS supersedes other applicable status values on output. If the column already exists and as long as any column value was set successfully, the provider returns this value instead of others that apply (such as DBSTATUS_S_ISNULL).
    • DBSTATUS_S_DEFAULT The provider skips this column when setting data.

    • DBSTATUS_S_IGNORE The provider skips this column when setting data.

    • DBSTATUS_S_ISNULL A null value was sent to the provider.

    • DBSTATUS_E_CANTCONVERTVALUE The provider was unable to match the type or metadata of the column definition with a type supported by the provider.

    • DBSTATUS_E_CANTCREATE The provider exceeded a limitation (such as the number of columns allowed) and was unable to add the column, or the provider did not create the column because it did not support a requested column flag in dwFlags of DBCOLUMNINFO.

    • DBSTATUS_E_INTEGRITYVIOLATION The column is a calculated or derived value and cannot be directly modified.

    • DBSTATUS_E_PERMISSIONDENIED The consumer did not have sufficient permission to add the column.

    • DBSTATUS_E_UNAVAILABLE On input, the status was DBSTATUS_S_OK, IColumnsInfo::GetColumnInfo did not return DBCOLUMNFLAGS_ISLONG for this column, and pData was a null pointer.

    cbDataLen

    On input, the length of the data value pointed to by pData. Ignored for fixed-length types.

Return Code

  • S_OK
    The provider successfully created or set the values of all of the columns.

  • E_INVALIDARG
    cColumns was not zero, and rgNewColumnInfo was a null pointer.

  • E_OUTOFMEMORY
    The provider was unable to allocate sufficient memory for this operation.

  • DB_S_ERRORSOCCURRED
    The provider was able to add or set the value of at least one column but was unable to do so for at least one column. The caller should examine the dwStatus value of each element of rgColumns to determine whether, and why, an individual column was not set.

  • DB_E_DELETEDROW
    The row is either a pending delete row or a row for which a deletion had already been transmitted to the data store.

  • DB_E_ERRORSOCCURRED
    An error occurred while setting data for one or more columns, and data was not successfully set for any columns. The caller should examine the dwStatus value of each element of rgColumns to determine whether, and why, an individual column was not set.

  • DB_E_NEWLYINSERTED
    DBPROP_CHANGEINSERTEDROWS on the source rowset was VARIANT_FALSE, and the method was called on a row for which the insertion has been transmitted to the data store.

  • DB_E_NOTSUPPORTED
    The provider does not support this method.

  • DB_SEC_E_PERMISSIONDENIED
    The provider was unable to set any columns due to a permission failure.

  • E_FAIL
    A provider-specific error occurred. No columns were added.

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

Comments

IRowSchemaChange::AddColumns sets the columns named by columnid in the rgNewColumnInfo array with the values pointed to by pData.

The provider first attempts to create new columns using the column metadata supplied in the elements of rgNewColumnInfo. If rgNewColumnInfo contains an element for a column that already exists, the provider sets dwStatus to DBSTATUS_S_ALREADYEXISTS and ignores the column metadata provided in rgNewColumnInfo. The attributes of an existing column cannot be altered. Consumers are not required to know the data types or maximum column sizes of the underlying data store's types. Using ulColumnSize, wType,and dwFlags, the provider determines the appropriate data type, maximum column size (which may exceed ulColumnSize), and other column attributes of the new column. Once the column is created, the consumer can call IColumnsInfo::GetColumnInfo to obtain the defined maximum length of the created column. If the provider is unable to create a column definition, it returns the appropriate status code for that column and does not attempt to set the column value. A failure creating or setting a column has no direct impact on the creation or setting of other row columns in the method call. Providers are not required to support all of the column flags listed for dwFlags and are allowed to ignore flags they don't support. If the provider fails column creation due to an unsupported flag, it should return a status of DBSTATUS_E_CANTCREATE.

Next the provider sets the row column values with the values supplied by the caller in rgColumns. If rgColumns is a null pointer, the provider creates the columns but does not set any column values. This behavior is identical to that provided by IRowChange::SetColumns. If rgColumns is supplied and if the dwStatus value passed on input is bad, the provider returns DBSTATUS_E_BADSTATUS. If the column is successfully created and set, dwStatus is set to either DBSTATUS_S_OK or DBSTATUS_S_ISNULL.

If all columns were created and set, the provider returns S_OK. If no columns were created and set, the provider returns DB_E_ERRORSOCCURRED. If at least one column was created and set and at least one column failed to be created and set, the provider returns DB_S_ERRORSOCCURRED. If a column is added but the value is not set, the method could return either of two return codes. DB_S_ERRORSOCCURRED means at least one column was added and set successfully. DB_E_ERRORSOCCURRED means no columns were added and set successfully. The dwStatus value indicates the problem, which may involve the add (DBSTATUS_E_ALREADYEXISTS) or the set (DBSTATUS_E_BADSTATUS or other) value. The dwStatus value for each column indicates which columns failed to be created or set.

The creation of new columns occurs immediately, even if the row object is in deferred mode. Changes to the column values depend on the deferred mode of the row object. If a row object does not have a source rowset or if changes to the source rowset are immediate, changes to all row column values are also immediate. If a row object has a source rowset and changes to this rowset are deferred, changes to all row object column values are also deferred. IRowsetUpdate::Update commits pending changes for row column values as well as for rowset columns. If the row object has a source rowset, newly created row columns will not appear in this rowset.

If the provider supports type conversions to or from the data types described by the DBCOLUMNINFO structure, it should implement IConvertType on row objects. This interface is used to report whether a given conversion is supported. Providers are strongly encouraged to delegate data type conversions to the OLE DB Data Conversion library (Oledb32.dll). For more information, see Data Conversion Library in Appendix H: Data Type Conversion Interfaces.

If a provider also supports the adding or modification of columns to base tables using IAlterTable, ITableCreation, ITableDefinition or ITableDefinitionWithConstraints, it needs to maintain the uniqueness of base table column IDs and row-specific column IDs. Providers should reject attempts to create columns with non-unique column IDs and return either DB_E_DUPLICATECOLUMNID or DBSTATUS_ALREADYEXISTS.

When setting row 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 AddColumns returns, it must call IUnknown::AddRef on the pointer before calling AddColumns.