Compartir a través de


ICommand::Execute

Executes the command.

Syntax

HRESULT Execute (
   IUnknown     *pUnkOuter,
   REFIID        riid,
   DBPARAMS     *pParams,
   DBROWCOUNT   *pcRowsAffected,
   IUnknown    **ppRowset);

Parameters

  • pUnkOuter
    [in] A pointer to the controlling IUnknown interface if the rowset is being created as part of an aggregate; otherwise, it is null.

  • riid
    [in] The requested IID for the rowset returned in *ppRowset. This interface is conceptually added to the list of required interfaces on the resulting rowset, and the method fails (E_NOINTERFACE) if that interface cannot be supported on the resulting rowset. If the command has any open rowsets, requesting an interface that is not supported on those open rowsets will generally return E_NOINTERFACE as it is not possible to change the properties supported on a command with open rowsets. In addition, specifying the IID of a nonmandatory interface that has not been explicitly requested through rowset properties set on a prepared command might reduce the provider's ability to optimize the command, because the provider might have to rebuild the access plan to satisfy the additional interface.

    If this is IID_NULL, ppRowset is ignored and no rowset is returned, even if the command would otherwise generate a rowset. Specifying IID_NULL is useful in the case of text commands that do not generate rowsets, such as data definition commands, as a hint to the provider that no rowset properties need to be verified.

    If riid is IID_IMultipleResults, the provider creates a multiple results object and returns a pointer to it in *ppRowset; it does this even if the command generates a single result. If the provider supports multiple results and the command generates multiple results but riid is not IID_IMultipleResults, the provider returns the first result and discards any remaining results. If riid is IID_IMultipleResults and the provider does not support multiple results, ICommand::Execute returns E_NOINTERFACE.

  • pParams
    [in/out] A pointer to a DBPARAMS structure that specifies the values for one or more parameters. In text commands that use parameters, if no value is specified for a parameter through pParams, an error occurs.

    struct DBPARAMS {
       void        *pData;
       DB_UPARAMS   cParamSets;
       HACCESSOR    hAccessor;
    };
    

    The elements of this structure are used as described in the following table.

    Element

    Description

    pData

    Pointer to a buffer from which the provider retrieves input parameter data and to which the provider returns output parameter data, according to the bindings specified by hAccessor. This pointer must be a valid pointer to a contiguous block of consumer-owned memory for the input and output parameter values. For more information, see Getting Data and Setting Data.

    When output parameter data is available to the consumer depends on the DBPROP_OUTPUTPARAMETERAVAILABILITY property.

    cParamSets

    The number of sets of parameters in *pData. If cParamSets is greater than one, the bindings described by hAccessor define the offsets within *pData for each set of parameters and cbRowSize (as specified in IAccessor::CreateAccessor) defines a single fixed offset between each of those values and the corresponding values for the next set of parameters. Sets of multiple parameters (cParamSets is greater than one) can be specified only if DBPROP_MULTIPLEPARAMSETS is VARIANT_TRUE and the command does not return any rowsets.

    hAccessor

    Handle of the accessor to use. If hAccessor is the handle of a null accessor (cBindings in IAccessor::CreateAccessor was 0), ICommand::Execute does not retrieve or return any parameter values.

    If the provider is able to determine the number of parameters in the command and the command text does not include parameters, the provider ignores this argument.

  • pcRowsAffected
    [out] A pointer to memory in which to return the count of rows affected by a command that updates, deletes, or inserts rows. If cParamSets is greater than one, *pcRowsAffected is the total number of rows affected by all of the sets of parameters specified in the execution. If the number of affected rows is not available, *pcRowsAffected is set to DB_COUNTUNAVAILABLE on output. If riid is IID_IMultipleResults, the value returned in *pcRowsAffected is either DB_COUNTUNAVAILABLE or the total number of rows affected by the entire command; to retrieve individual row counts, the consumer calls IMultipleResults::GetResult. If the command does not update, delete, or insert rows, *pcRowsAffected is undefined on output. If pcRowsAffected is a null pointer, no count of rows is returned.

    pcRowsAffected is undefined if ICommand::Execute returns DB_S_ASYNCHRONOUS. For asynchronously executed commands, the consumer should call IDBAsynchStatus::GetStatus to obtain the number of rows affected in pulProgress.

  • ppRowset
    [in/out] A pointer to the memory in which to return the rowset's pointer. If ppRowset is a null pointer, no rowset is created. However, if the DBPROP_OUTPUTSTREAM property is set and the result of ICommand::Execute is a stream object, a null pointer is an acceptable value.

    If ppRowset is not a null pointer and an interface on a stream object was requested, the provider returns to *ppRowset the interface pointer set in the DBPROP_OUTPUTSTREAM property. The consumer must release the interface pointer in *ppRowset when it is no longer needed.

    If *ppRowset is a null pointer, the provider did not write any results to the stream specified in DBPROP_OUTPUTSTREAM.

Return Code

  • S_OK
    The method succeeded. In all DBPROP structures returned by the method, dwStatus is set to DBPROPSTATUS_OK; the status of all input parameters bound by the accessor is set to DBSTATUS_S_OK or DBSTATUS_S_ISNULL; and the status of all output parameters bound by the accessor is set to DBSTATUS_S_OK, DBSTATUS_S_ISNULL, or DBSTATUS_S_TRUNCATED ? or is unknown because the parameter value has not been returned yet.

  • DB_S_ASYNCHRONOUS
    The method has initiated asynchronous creation of the rowset. The consumer can call IDBAsynchStatus to poll for status or IConnectionPointContainer to obtain the IID_IDBAsynchNotify connection point. Attempting to call any other interfaces may fail, and the full set of interfaces may not be available on the object until asynchronous initialization of the rowset has completed. DB_S_ASYNCHRONOUS should be returned before DB_S_ERRORSOCCURRED.

  • DB_S_ERRORSOCCURRED
    This can be returned for any of the following reasons:

    • The command was executed, but an error occurred while returning one or more output parameter values. To determine which output parameters were not 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.

    • The command was an SQL singleton SELECT WHERE statement, and one or more output parameters could not be set because the WHERE clause returned zero rows. In this case, the provider should set all returned columns to DBSTATUS_E_UNAVAILABLE. However, some providers cannot distinguish this case from the case where the WHERE clause returned a single row containing null values, and instead set all output parameters to NULL.

    • The rowset was opened, but one or more properties ? for which the dwOptions element of the DBPROP structure was DBPROPOPTIONS_OPTIONAL ? were not set. The consumer calls IRowsetInfo::GetProperties to determine which properties were set.

    DB_S_ASYNCHRONOUS should be returned before DB_S_ERRORSOCCURRED. Once rowset population is complete, the consumer can see DB_S_ERRORSOCCURRED either by calling IDBAsynchStatus::GetStatus or by receiving IDBAsynchNotify::OnStop.

    DB_S_ERRORSOCCURRED should be returned before DB_S_NOTSINGLETON because the status values can be checked, and providers are not required to return DB_S_NOTSINGLETON.

  • DB_S_NOTSINGLETON
    The provider supports returning row objects on ICommand::Execute, and the consumer requested a row object but the result was not a singleton. A row object of the first row of the rowset is returned. Returning this result may be expensive, so providers are not required to do so. If DB_S_ERRORSOCCURRED also applies to the execution of this method, it takes precedence over DB_S_NOTSINGLETON.

  • DB_S_STOPLIMITREACHED
    Execution has been stopped because a resource limit has been reached. The results obtained so far have been returned. Execution cannot be resumed.

    Multiple sets of parameters were specified, and one or more (but not all) of the parameters have been processed prior to the command being canceled by ICommand::Cancel or IDBAsynchStatus::Abort.

    This return code takes precedence over DB_S_ERRORSOCCURRED. That is, if the conditions described here and in those described in DB_S_ERRORSOCCURRED both occur, the provider returns this code. When the consumer receives this return code, it should also check for the conditions described in DB_S_ERRORSOCCURRED.

  • E_FAIL
    A provider-specific error occurred.

  • E_INVALIDARG
    riid was not IID_NULL, and ppRowset was a null pointer. Any streams used to pass input parameters are not released.

    The parameter information was invalid. Parameter information may be invalid for any of the following reasons. In all cases, any streams used to pass input parameters are not released.

    • pParams was not ignored, cParamSets in the DBPARAMS structure pointed to by pParams was greater than one, ppRowset was not a null pointer, and the provider does not support multiple results.

    • pParams was not ignored, and in the DBPARAMS structure pointed to by pParams, pData was a null pointer.

    • pParams was not ignored, was not a null pointer, and in the DBPARAMS structure pointed to by pParams, cParamSets was zero.

  • E_NOINTERFACE
    The rowset did not support the interface specified in riid.

    riid was IID_IMultipleResults, and the provider did not support multiple results objects.

  • DB_E_ABORTLIMITREACHED
    Execution has been aborted because a resource limit has been reached. For example, a query timed out. No results have been returned.

  • DB_E_BADACCESSORHANDLE
    pParams was not ignored, and hAccessor in the DBPARAMS structure pointed to by pParams was invalid. Any streams used to pass input parameters are not released.

  • DB_E_BADACCESSORTYPE
    hAccessor in the DBPARAMS structure pointed to by pParams was not the handle of a parameter accessor. Any streams used to pass input parameters are not released.

  • DB_E_CANCELED
    The command was canceled by a call to ICommand::Cancel on another thread. No records were affected.

  • DB_E_CANTCONVERTVALUE
    A literal value in the command text could not be converted to the type of the associated column for reasons other than data overflow.

  • DB_E_DATAOVERFLOW
    A literal value in the command text overflowed the type specified by the associated column.

  • DB_E_ERRORSINCOMMAND
    The command text contained one or more errors. Providers should use OLE DB error objects to return details about the errors.

  • DB_E_ERRORSOCCURRED
    The method failed due to one or more nonvalid input parameter values. To determine which input parameter values were not valid, the consumer checks the status values. (For a list of status values that can be returned by this method, see "Status Values Used When Setting Data" in Status.) If any streams were used to pass input parameters, only those with the status value equal to DBSTATUS_S_OK on input are released; otherwise, no attempt is made to release the stream. If the consumer provides storage objects for additional bound parameters that are not used by the current command, it is a consumer programming error and the provider does not attempt to release these parameters.

    The command was not executed, and no rowset was returned because one or more properties ? for which the dwOptions element of the DBPROP structure was DBPROPOPTIONS_REQUIRED ? were not set.

    Multiple parameter sets were passed with a command that returns a rowset. (Some providers might not return this error.)

  • DB_E_INTEGRITYVIOLATION
    A literal value in the command text violated the integrity constraints for the column.

  • DB_E_NOAGGREGATION
    pUnkOuter was not a null pointer, and the provider is an OLE DB 1.0 or 1.1 provider that does not support aggregation of the rowset object being created. Any streams used to pass input parameters are not released.

    pUnkOuter was not a null pointer, and riid was not IID_IUnknown. Any streams used to pass input parameters are not released.

  • DB_E_NOCOMMAND
    No command text was currently set on the command object. Any streams used to pass input parameters are not released.

  • DB_E_NOTABLE
    The specific table or view does not exist in the data store.

  • DB_E_NOTFOUND
    The provider supports row objects, a row was requested via riid or DBPROP_IRow, and no rows satisfied the selection criteria of the command.

  • DB_E_PARAMNOTOPTIONAL
    A value was not supplied for a required parameter.

    The command text used parameters and pParams was a null pointer.

  • DB_E_PARAMUNAVAILABLE
    Provider cannot derive parameter information, and ICommandWithParameters::SetParameterInfo has not been called.

  • DB_SEC_E_PERMISSIONDENIED
    The consumer did not have sufficient permission to execute the command. For example, a rowset-returning command specified a column for which the consumer does not have read permission, or an update command specified a column for which the consumer does not have write permission.

  • DB_E_OBJECTOPEN
    The provider would have to open a new connection to support the operation, and DBPROP_MULTIPLECONNECTIONS is set to VARIANT_FALSE. Any streams used to pass input parameters are not released.

    If a session is enlisted in a global transaction and a command requires the creation of an additional connection, the provider should return DB_E_OBJECTOPEN. Providers written prior to OLE DB 2.6 may return E_FAIL.

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 HRESULTs for the reasons listed in the corresponding DBBINDSTATUS values in IAccessor::CreateAccessor. In all cases, any streams used to pass input parameters are not released.

  • E_NOINTERFACE

  • DB_E_BADBINDINFO

  • DB_E_BADORDINAL

  • DB_E_BADSTORAGEFLAGS

  • DB_E_UNSUPPORTEDCONVERSION

If the command is a row-returning command, such as an SQL SELECT statement, the result of this method is a rowset over the result rows. If no rows match the command, the rowset is still created. The resulting rowset is fully functional and can be used, for example, to insert new rows or determine column metadata. If the command is a non-row-returning command, such as an SQL INSERT statement, *ppRowset is set to NULL and no rowset is returned.

If the command returns multiple results (row counts, rowset objects, or row objects), the consumer requests a multiple-results object by setting riid to IID_IMultipleResults. ICommand::Execute creates the multiple results object and returns an IMultipleResults interface pointer to it in *ppRowset. The consumer repeatedly calls IMultipleResults::GetResult to retrieve the results in order. For more information, see Multiple Results.

Rowsets returned by IMultipleResults::GetResult have the properties set as defined by the command that created the multiple results object. These properties are identical for each result set. There is no way to set different properties for results of a multiple result.

If any or all parameters fail and the provider does not support errors within an array of parameters (that is, the command fails if any or all of the parameters fail), the provider returns DB_E_ERRORSOCCURRED and returns any error information for the failed parameters in their status bindings.

If any or all parameters fail and the provider supports errors within an array of parameters, the provider returns DB_S_ERRORSOCCURRED, sets pcRowsAffected to the number of successful parameters, and returns any error information for the failed parameters in their status bindings.

When populating output parameters and the command produces a nonsingleton result, the provider returns S_OK and populates the output parameters with values from the first row of the result. If the underlying command processor does not support nonsingleton results with output parameters, the provider returns a provider-specific error.

If ICommand::Execute is called multiple times for a single command, with or without changes to the command text, the outcome may reflect changes in the underlying stored data, depending on the isolation level specified for the surrounding transaction.

When executing a command whose command text is a sequence of subcommands and also requesting a multiple results object, the provider must ensure that subcommands are executed in the order they appear in the command text and that any command whose results have been retrieved via IMultipleResults::GetResult has been executed.

It is provider-specific whether each of the subcommands is executed at ICommand::Execute or just-in-time for IMultipleResults::GetResult, and it is also provider-specific whether subcommands whose results have not been obtained have been executed.

ICommand::Execute can be called when a rowset is already open on the command if the only change between the calls is a change in the value of existing parameters. (Calls to ICommandWithParameters::SetParameterInfo will fail.) Methods that modify the command (ICommandPrepare::Prepare, ICommandPrepare::Unprepare, ICommandProperties::SetProperties, and ICommandText::SetCommandText) while a rowset is open will fail and return DB_E_OBJECTOPEN. Each call to ICommand::Execute creates a new rowset, which must be explicitly released by IUnknown::Release.

ICommand::Execute does not affect the prepared state of a command.

The consumer determines whether the command supports parameters by calling QueryInterface for ICommandWithParameters. If this interface is exposed, the command supports parameters; if it is not exposed, the command does not support parameters. If the command does not support parameters, ICommand::Execute ignores pParams. However, if the command text includes parameters, ICommand::Execute returns DB_E_ERRORSINCOMMAND.

Consumers should not assume providers will derive parameter information. Use ICommandWithParameters::SetParameterInfo to explictly set or ICommandWithParameters::GetParameterInfo to explictly derive parameter information.

If an input parameter value is not specified, ICommand::Execute returns DB_E_PARAMNOTOPTIONAL. If the provider cannot describe parameters and the consumer has not called ICommandWithParameters::SetParameterInfo for all parameters, the behavior of ICommand::Execute is undefined. For example, ICommand::Execute might guess at the parameter information or it might fail completely. For more information, see SetParameterInfo.

If ICommand::Execute returns DB_S_ERRORSOCCURRED or DB_E_ERRORSOCCURRED, the consumer can immediately call ICommandProperties::GetProperties with the DBPPROPSET_PROPERTIESINERROR property set to return the properties that could not be set. For more information, see Property Sets in Appendix C: OLE DB Properties.

ICommand::Execute does not alter the value of any properties. That is, ICommandProperties::GetProperties returns the same value for a property whether or not it is called before or after Execute and whether or not Execute succeeded or failed. However, if a property value is not required, IRowsetInfo::GetProperties can return a different value for that property than ICommandProperties::GetProperties. For more information, see IRowsetInfo::GetProperties.

If several threads concurrently request execution of a given command, the corresponding executions are serialized and each thread will block until its corresponding execution concludes.

ICommand::Execute can fail even if ICommandPrepare::Prepare has succeeded; this may be the case if, for example, the underlying schema has changed between the Prepare and Execute calls and the command text had therefore become illegal.

Except where otherwise indicated, the provider frees all streams used to pass input parameters.

ICommand::Execute operates on the last command specified by either ICommandText::SetCommandText or ICommandStream::SetCommandStream. If Execute is called again, the same command is re-executed even if the command is contained in a stream whose contents are normally inaccessible after having been read once.

See Also

Reference

ICommand::Cancel

ICommandPrepare::Prepare

ICommandText::SetCommandText

ICommandWithParameters::SetParameterInfo