IMultipleResults::GetResult returns the next in a series of multiple results from the provider. A result is returned for each separate statement in the command text or from each set of parameters passed to a command. If the next result is the result of a row-returning command or operation, 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 next result is the result of a non-row-returning command, such as an SQL INSERT statement, *ppRowset is set to NULL and *pcRowsAffected is set to the count of rows affected, if applicable.
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.
Providers will generally be able to process only one result at a time. For maximum interoperability, consumers should free any rowset obtained by a previous call to IMultipleResults::GetResult before requesting the next result.
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.
Providers may check the entire command text for errors at execute time or may check the command text associated with each result when that result is retrieved. Therefore, the syntax errors returned by ICommand::Execute can also be returned by IMultipleResults::GetResult. In this case, the next call to IMultipleResults::GetResult moves on to the next result or returns DB_S_NORESULT if no more results are available.
When IMultipleResults::GetResult returns an error, its behavior depends on the error that occurred, as in the following scenarios:
If IMultipleResults::GetResult returns E_INVALIDARG, DB_E_NOAGGREGATION or DB_E_OBJECTOPEN, the current result is still available. Assuming there are no other errors, the next call to IMultipleResults::GetResult returns the current result.
If IMultipleResults::GetResult returns any other error, the current result is lost. The next call to IMultipleResults::GetResult returns either the next result or DB_S_NORESULT if the error caused the provider to lose all remaining results. Providers that can recover the current result in this situation must discard it and return the next result.
The following example shows how a consumer might process multiple results:
hr = pICommandText->Execute(pUnkOuter, IID_IMultipleResults, pParams,
&cRowsAffected,(IUnknown**)&pIMultipleResults);
if (pIMultipleResults) {
while(hr != DB_S_NORESULT) {
if(SUCCEEDED(hr = pIMultipleResults->GetResult(pUnkOuter, 0,
IID_IRowset, &cRowsAffected, &pIRowset))) {
if(pIRowset) {
// The next result is a rowset. Process the rowset.
pIRowset->Release();
} else {
// The next result is not a rowset. Process the
// nonrowset result.
}
} else {
// Process error from GetResult.
break;
}
}
pIMultipleResults->Release();
}