The focus this week has been OLE DB objects, their interfaces, and some simple OLE DB applications. OLE DB also provides a means for you to build robust applications by using mechanisms to integrate error handling into your applications. The first step in error handling is to examine the value returned by a method, which is where today's discussion of OLE DB error handling begins. OLE DB uses the basic error-handling techniques of Automation, the technology formerly known as OLE Automation, and adds another layer of error handling that can return multiple provider-specific errors. The goal of Day 21 is to show you how to integrate these techniques into your own applications.
Today you will
Although all the OLE DB interface methods discussed this week return an HRESULT type value, the OLE DB code you have written so far assumes that all method calls always execute successfully. Obviously, this approach isn't the way to build a robust application that can handle unexpected situations. Therefore, the first step in adding robustness to OLE DB applications is to check the method's result value.
NOTE |
A robust application can handle all error conditions without crashing. As an application developer, you have the responsibility of handling all errors that your application might generate. |
As you know, the HRESULT type return value indicates the success or failure of a method. (Later today you will explore the status codes that a method can return.) Visual C++ provides two macros that you can use to determine generally whether a method was successful. These macros are aptly named SUCCEEDED and FAILED. The SUCCEEDED macro returns true if the call to the method was successful, and the FAILED macro returns true if the call to the method was unsuccessful. If a call to a method is successful, it returns the constant value S_OK. A method can return other success and error values as well. Typically, the success value constants begin with an S_ or DB_S_, and the error value constants begin with an E or DB_E. You will learn about these status value constants later today, also. Listing 21.1 demonstrates how to check the HRESULT value of a method to determine whether it executed successfully.
NOTE |
The standard error and success return codes are defined in the Visual C++ documentation. |
Listing 21.1 Checking the HRESULT Value of a Method
1: // Create a Command object... 2: if(FAILED(pCreateSession->CreateSession(NULL, IID_IDBCreateCommand, 3: (IUnknown **) &pCreateCommand))) { 4: printf("The Create Session Method Failed!\n"); 5: };
As you can see, checking the status of a call to an OLE DB method is fairly simple. That information enables your application to take the necessary steps to prevent a failure. In addition, OLE DB and Automation support interfaces that can help you retrieve more-detailed information regarding the failure of a method. The following section explains how to integrate these interfaces to retrieve additional error information. The immediate goal here is to build a procedure you can use in your application to display this additional error information.
The OLE DB specification is an extension of the Automation interface. Automation defines two interfaces that assist in the error-handling process. These interfaces are not required by OLE DB data providers. The first interface, ISupportErrorInfo, determines whether the additional support is provided. The second interface, IErrorInfo, assists in retrieving additional specific error information, including a more complete description of the error and whether any further information is available in an associated help file.
The ISupportErrorInfo interface determines whether an object supports the necessary interfaces to retrieve additional error information. The ISupportErrorInfo defines a single method, InterfaceSupportsErrorInfo, which is defined as follows:
HRESULT InterfaceSupportsErrorInfo(REFIID riid);
This method takes a single parameter, riid, which represents the interface you are checking to determine whether it supports additional error information. If the interface supports additional error information, the InterfaceSupportsErrorInfo method returns S_OK.
Listing 21.2 demonstrates the first step in creating a procedure that retrieves and displays the additional error information if it's supported. The procedure DispErrorInfo takes two parameters: a pointer to the interface that generated the error and the globally unique identifier (GUID) of that interface. Because this procedure should function for any type of OLE DB object, it will pass the pointer to the interface that generated the error as a pointer to the generic IUnknown type.
CAUTION |
You must always call the InterfaceSupportsErrorInfo method before attempting to retrieve additional error information. If the interface doesn't support additional error information and you call any of the additional error-information methods, you will generate yet another error! Never create error-handling routines that generate more errors themselves. |
Listing 21.2 The First Step in Building a Procedure
to Handle and Display OLE DB Errors
1: HRESULT DispErrorInfo(IUnknown *pErrorInt, GUID ErrorIID) { 2: ISupportErrorInfo *pSupportErrorInfo; 3: 4: // Obtain Access to the ISupportErrorInfo Interface 5: if(SUCCEEDED(pErrorInt->QueryInterface(IID_ISupportErrorInfo, 6: (void **) &pSupportErrorInfo))) { 7: // Check if Extended Error Information is Available 8: if(pSupportErrorInfo->InterfaceSupportsErrorInfo(ErrorIID) == S_OK) { 9: // Process the Error Information Available Here!... 10: } else { 11: cerr << "Extended Error Information Unavailable!\n"; 12: }; 13: pSupportErrorInfo->Release(); 14: } else { 15: cerr << "Could Not Obtain Access To The ISupportErrorInfo Interface\n"; 16: cerr << "Additional Error Information Unavailable!\n"; 17: }; 18: return S_OK; };
As Listing 21.2 demonstrates, after the ISupportErrorInfo interface is successfully obtained, you can use the InterfaceSupportsErrorInfo method to determine whether the object supports the IErrorInfo interface. The next section explains the IErrorInfo interface.
The IErrorInfo interface is the generic Automation interface that retrieves extended error information about a single error. However, OLE DB objects don't use this interface directly. As you already know, the ISupportErrorInfo interface determines whether the application supports the IErrorInfo interface. The IErrorInfo interface defines five methods: GetDescription, GetGUID, GetHelpContext, GetHelpFile, and GetSource. These methods are defined as follows:
HRESULT GetDescription(BSTR *pbstrDesc); HRESULT GetGUID(GUID *pGUID); HRESULT GetHelpContext(DWORD *pwHelpContext); HRESULT GetHelpFile(BSTR *pbstrHelpFile); HRESULT GetSource(BSTR *pbstrSource);
The GetDescription method returns a string that contains a natural-language description of the error that occurred. This description is suitable to display to an end user.
The GetGUID method returns the interface ID of the interface that generated the error. If the error isn't attributable to a specific interface, the value of the GUID is set to DBGUID_NULL.
The GetHelpContext and GetHelpFile methods retrieve the name of the help file and help file lookup. This information can launch the help viewer and place the user in a context that displays additional error information. These values are returned only if the data provider supports a help file. The GetHelpContext method returns a context value, and the GetHelpFile method returns a string that contains the name of the help file, including the path.
The GetSource method returns the name of the source operating-system object that generated the error. The source name is generally the name of the dynamic link library (DLL) that encapsulates the data provider interfaces.
NOTE |
The consumer must use the SysFreeString method to deallocate any string values that the IErrorInfo interfaces return. |
The IErrorInfo interface works quite well for standard COM objects. However, the OLE DB has two requirements that the standard IErrorInfo interface can't meet:
Therefore, OLE DB defines three additional interfaces to overcome these limitations. These interfaces are IErrorRecords, IErrorLookup, and ISQLErrorInfo. The IErrorRecords interface returns multiple errors simultaneously. The IErrorLookup interface provides extended error-description information. Finally, the ISQLErrorInfo interface returns custom SQL error information.
A detailed explanation of these interfaces and the methods they provide follows. When you understand how to use these interfaces, you can integrate them into the completed DispErrorInfo procedure started in Listing 21.1.
Rather than return one record as defined by the IErrorInfo interface, OLE DB methods can return multiple errors. The IErrorRecords interface navigates and manages this collection of error records. The reason OLE DB needs to return multiple errors is that an error can have a cascading effect. This record structure enables these multiple cascading errors to be captured and returned. Each error record contains the following information:
I explain each of the preceding components in the following discussion of the specific OLE DB error interfaces. The IErrorRecords interface defines the following methods: AddErrorRecord, GetBasicErrorInfo, GetCustomErrorObject, GetErrorInfo, GetErrorParameters, and GetRecordCount. These methods are defined as follows:
HRESULT GetBasicErrorInfo(ULONG lRecNum, ERRORINFO *pErrorInfo); HRESULT GetCustomErrorObject(ULONG lRecNum, REFIID riid, IUnknown **ppCustomErrorInt); HRESULT GetErrorInfo(ULONG lRecNum, LCID LocaleID, IErrorInfo **ppErrorInfoInt); HRESULT GetErrorParameters(ULONG lRecNum, DISPPARAMS *pDispParam); HRESULT GetRecordCount(ULONG *plNumRecs); HRESULT AddErrorRecord(ERRORINFO *pErrorInfo, DWORD dwLookupID, DISPPARAMS *pDispParam, IUnknown *pCustomErrorInt, DWORD dwDynamicID);
The GetBasicErrorInfo method retrieves the basic ERRORINFO structure for the record number specified in the lRecNum parameter. The ERRORINFO structure holds basic information about an error. The structure is defined as follows:
typedef struct tagERRORINFO HRESULT hrError; DWORD dwMinor; CLSID clsid; IID iid; DISPID dispid; } ERRORINFO;
The hrError field contains the HRESULT error value for the record specified. Each record can have an HRESULT value different from the one that the method initially returned. The dwMinor field contains a provider-specific error value. You must consult the documentation for the data provider for more information about the meanings of this value. The clsid field contains the class ID of the OLE DB object that generated this error. The iid parameter contains the interface ID of the interface that generated this error. If the method belongs to multiple interfaces, the interface ID where the method is defined first is returned. The dispid field contains the method that generated the error. This method ID may or may not be defined, depending on the data provider.
The GetCustomErrorObject method retrieves a provider-specific customer error. OLE DB provides one custom error interface, ISQLErrorInfo (discussed shortly), for providers that support the SQL command language. The GetCustomErrorObject method parameter lRecNum specifies the error record number to access. The riid parameter specifies the interface ID of the custom error object you want to retrieve. The ppCustomErrorInt parameter returns a pointer to the interface requested. If the requested custom error interface isn't available, ppCustomErrorInt will be NULL on return. If this method succeeds, ppCustomErrorInt returns S_OK.
The GetErrorInfo method retrieves an IErrorInfo interface for the specified record number. The lRecNum parameter specifies the record number to retrieve. The LocalID parameter specifies the locale ID. The locale ID specifies the current location and selects the appropriate language version of the error descriptions. The ppErrorInfoInt parameter returns a pointer to IErrorInfo interface for the selected record number.
TIP |
To retrieve the default system locale ID, use the standard Visual C++ method GetSystemDefaultLCID(). |
The GetErrorParameters method retrieves error message parameters. Some error messages might use parameters, as in the following example: Access to table <table1> denied. In this case, <table1> is a parameter. If the parameter <table1> had the value CUSTOMERS, the error message would be automatically reformatted as follows: Access to table CUSTOMERS denied. A consumer usually won't use a parameter structure without knowing which values are available in that structure. The lRecNum parameter specifies the record number. The pDispParams parameter retrieves the error message parameters.
The GetRecordCount method returns the number of error records available. The parameter plNumRecs returns the number of error records available. Error records have the index values 0 to plNumRecs -1.
The AddErrorRecord method is used only by data providers. It adds a new error record to the error records collection. The pErrorInfo structure holds a pointer to a filled-in ERRORINFO structure, specifying information about the error. The dwLookupID specifies the error's lookup ID. The pDispParam parameter specifies the error's message parameters. The pCustomErrorInt parameter specifies the custom error object, if applicable. The dwDynamicID parameter specifies the error ID if the provider uses dynamic errors; otherwise, it has a value of 0. You will generally not use this method.
You will use the IErrorRecords interface extensively to complete the DispErrorInfo procedure from Listing 21.2. In its final form, the procedure loops through and retrieves the information in each error record. First, though, you need to look at the IErrorLookup and ISQLErrorInfo interfaces.
Data providers use the IErrorLookup interface to retrieve help file information, combine the error parameters with the error message to create a completed error message, and release dynamic error information. The IErrorLookup interface defines three methods: GetErrorDescription, GetHelpInfo, and ReleaseErrors. These methods are defined as follows:
HRESULT GetErrorDescription(HRESULT hError, DWORD dwLookupID, DISPPARAMS *pDispParam, LCID lcid, BSTR *pErrorObject, BSTR *pDesc); HRESULT GetHelpInfo(HRESULT hError, dwLookupID, LCID lcid, BSTR *pHeloFileName, DWORD *pContext); HRESULT ReleaseErrors(const DWORD dwDynErrorID);
The GetDescription method retrieves the source error object string, specified in the pErrorObject parameter, and the error description, specified in the pDesc parameter. The GetHelpInfo method retrieves an error's associated help file information, if applicable. The GetErrorDescription and GetHelpInfo functions return BSTRs that must be freed by the caller, using SysFreeString.
The final error-related interface covered today is the ISQLErrorInfo interface. This interface is used in the custom error object pointer of an error record. You access the ISQLErrorInfo interface by using the GetCustomErrorObject method of the IErrorRecord interface. The ISQLErrorInfo interface defines a single method: GetSQLInfo. This method is defined as follows:
HRESULT GetSQLInfo(BSTR *pSQLStateStr, LONG *plSQLErrorNum);
The pSQLStateStr parameter returns a string containing the current SQL state. The plSQLErrorNum returns the provider-specific SQL error number. The pSqlStateStr is an [out] bstr, so the caller must free it by using SysFreeString.
Armed with the information provided by these error interfaces, you are ready to return to the DispErrorInfo procedure in Listing 21.2. The final procedure accesses the IErrorRecord interface and loops through each available error record, one at a time. DispErrorInfo retrieves an IErrorInfo interface for each error record and uses that IErrorInfo interface to access the error description, source, and GUID. The GetCustomErrorObject is accessed for each record. If a ISQLErrorInfo interface is available, the current SQL state and error number are also displayed. The complete DispErrorInfo procedure appears in Listing 21.3.
NOTE |
Remember to use the SysFreeString method to release the returned string memory. The BSTR type is a Unicode type string. (Refer to Day 19, "Navigating the Result of a Query," for more information about the methods available to process Unicode strings.) |
Listing 21.3 The Completed DISPERRORINFO Procedure
1: HRESULT DispErrorInfo(IUnknown *pErrorInt, GUID ErrorIID) { 2: ISupportErrorInfo *pSupportErrorInfo; 3: IErrorInfo *pErrorInfo, 4: *pErrorInfoRecord; 5: IErrorRecords *pErrorRecords; 6: ISQLErrorInfo *pSQLErrorInfo; 7: BSTR pDescription = NULL; 8: BSTR pSource = NULL; 9: BSTR pSQLState = NULL; 10: GUID ErrorGUID; 11: ULONG i, 12: lNumRecs; 13: LONG lSQLErrorNum; 14: HRESULT retcode = S_OK; 15: 16: // Obtain Access to the ISupportErrorInfo Interface 17: if(SUCCEEDED(pErrorInt->QueryInterface(IID_ISupportErrorInfo, 18: (void **) &pSupportErrorInfo))) { 19: // Check if Extended Error Information is Available 20: if(SUCCEEDED(pSupportErrorInfo->InterfaceSupportsErrorInfo (ErrorIID))) { 21: // Access the Error Info interface 22: if(SUCCEEDED(GetErrorInfo(0,&pErrorInfo))) { 23: // Retrieve the Error Records Interface 24: if(SUCCEEDED(pErrorInfo->QueryInterface(IID_IErrorRecords, 25: (void **) &pErrorRecords))) { 26: // Retrieve the Number of Error Records 27: if(SUCCEEDED(pErrorRecords->GetRecordCount(&lNumRecs))) { 28: for(i=0; i < lNumRecs; i++) { 29: // Get the Error Info Interface 30: pErrorRecords- >GetErrorInfo(i,GetSystemDefaultLCID(), 31: &pErrorInfoRecord); 32: // Get the Error Description 33: pErrorInfoRecord->GetDescription(&pDescription); 34: // Get the Error Source 35: pErrorInfoRecord->GetSource(&pSource); 36: // Get the Error GUID 37: pErrorInfoRecord->GetGUID(&ErrorGUID); 38: // Print the Error Record Interface 39: fprintf(stderr,"Error GUID: %lx\n",ErrorGUID); 40: fprintf(stderr,"Source: %S\n",pDescription); 41: fprintf(stderr,"Description: %S\n\n",pDescription); 42: // Free the Strings 43: SysFreeString(pDescription); 44: SysFreeString(pSource); 45: // Get SQL State if Available 46: if(SUCCEEDED(pErrorRecords->GetCustomErrorObject(i, 47: IID_ISQLErrorInfo, 48: (IUnknown **) &pSQLErrorInfo))) { 49: pSQLErrorInfo->GetSQLInfo(&pSQLState, &lSQLErrorNum); 50: fprintf(stderr,"SQL State: %S\n",pSQLState); 51: fprintf(stderr,"SQL Error Number: %ld",lSQLErrorNum); 52: SysFreeString(pSQLState); 53: pSQLErrorInfo->Release(); 54: }; 55: // Release the Interface 56: pErrorInfoRecord->Release(); 57: }; 58: } else { 59: fprintf(stderr,"Can't retrieve the number of error records!\n"); 60: retcode = E_FAIL; 61: }; 62: pErrorRecords->Release(); 63: } else { 64: fprintf(stderr,"Can't retrieve the ErrorRecords interface\n"); 65: retcode = E_FAIL; 66: }; 67: pErrorInfo->Release(); 68: } else { 69: fprintf(stderr,"Can't retrieve the ErrorInfo interface.\n"); 70: retcode = E_FAIL; 71: }; 72: pSupportErrorInfo->Release(); 73: } else { 74: fprintf(stderr,"Extended Error Information Unavailable!\n"); 75: retcode = E_FAIL; 76: }; 77: } else { 78: fprintf(stderr, 79: "Could Not Obtain Access To The ISupportErrorInfo Interface\n"); 80: fprintf(stderr,"Additional Error Information Unavailable!\n"); 81: retcode = E_FAIL; 82: }; 83: return(retcode); 84: };
When you call an OLE DB method, you should check the HRESULT
return value, as I mentioned at the beginning of the day. If the
method fails, you can call the DispErrorInfo procedure
to display any additional error information that's available.
Listing 21.4 demonstrates how to integrate the DispErrorInfo
method into an OLE DB method call.
Listing 21.4 How to Integrate the DISPERRORINFO
Procedure into an OLE DB Method Call
1: if(FAILED(pCommandText->Execute(NULL, IID_Rowset, NULL, &cNumRows, 2: (IUnknown **) &pRowset))) { 3: // The Execute method Failed! Display Error! 4: DispErrorInfo(pCommandText,IID_ICommandText); 5: // Exit and call free pCommandText and CoUninitialize?... 6: exit(0); 7: };
So far, you have learned about Automation and OLE DB error-handling interfaces, created a procedure to assist in the interpretation of errors that occurred, and integrated the error-handling interfaces into your applications. Here is a review of the basic steps in error handling:
Now that you know what a data consumer expects from a data provider, the data provider implementation requirements should be easy to understand. The final part of today's discussion of error handling explains how to implement error handling from the data provider side, including how a multithreaded environment affects data provider error handling.
Listing 21.5 demonstrates how an error is created and returned by a data provider method. The following survey of the basic steps involved in returning an error from a provider will help you understand that listing:
The SetErrorInfo method sets the current ErrorInfo
object, and the GetErrorInfo method retrieves the current
ErrorInfo object.
Listing 21.5 How an OLE DB Data Provider Returns
an Error
1: IErrorInfo pErrorInfoObj = NULL; 2: IErrorRecords pErrorRecs; 3: ERRORINFO ErrorInf; 4: 5: // Clear any current errors 6: SetErrorInfo(0, NULL); 7: 8: // Perform whatever is necessary to implement the method 9: // Save error result in hrError and set Error flag 10: 11: // Check if an Error Occurred? 12: if(Error) { 13: if(FAILED(GetErrorInfo(0, &pErrorInfoObj)) || (!pErrorInfoObj)) { 14: pClassFactoryObject->CreateInstance(NULL, 15: CLSID_EXTENDEDERRORINFO, (void *) &pErrorInfoObj); 16: }; 17: if (pErrorInfoObj) { 18: // Create the ERRORINFO record 19: pErrorInfoObj->QueryInterface(IID_IErrorRecords, (void *) &pErrorRecs); 20: ErrorInf.hrError = hrError; // Set error result 21: ErrorInf.dwMinor = INTERNAL_ERROR; // Set Internal Error // Number 22: ErrorInf.clsid = CURRENT_CLSID; // Set the Current CLSID 23: ErrorInf.iid = IID_CURRENT; // Set current IID 24: ErrorInf.dispid = DISPID_CURRENT; // Set current DISPID 25: 26: // Add the Error Record 27: pErrorRecs->AddErrorRecord(&ErrorInf, ErrorInf.dwMinor, 28: NULL, NULL, 0); 29: 30: // Set the Error 31: SetErrorInfo(0,pErrorInfo); 32: 33: // Release Error Interfaces 34: pErrorRecs->Release(); 35: pErrorInfo->Release(); 36: pErrorInfoObj->Release(); 37: } 38: };
When operating in a multithreaded application, an error message generated by a previously called method might be sitting in the message queue when another message is called. (Recall that in the OLE DB environment, each application thread has only one error object.) To clear out the error message queue, the OLE data provider must call the SetErrorInfo method when a method is called. This step ensures that only the most current errors are in the queue on return.
The first thing you did today was to check the HRESULT
of a method to determine whether it succeeded. Table 21.1 lists
the HRESULT values specifically defined by OLE DB. Refer
also to the Visual C++ documentation for information about generic
HRESULT constants.
Warning Results | |
DB_S_BADROWHANDLE | A row handle is invalid. |
DB_S_BOOKMARKSKIPPED | A bookmark was skipped for a row that was deleted or filtered. |
DB_S_BUFFERFULL | The buffer that holds fields or parameters is full. |
DB_S_CANTRELEASE | A lock could not be released until the transaction is complete. |
DB_S_COLUMNSCHANGED | While re-executing a query during a cursor reposition operation, the order or number of columns changed. |
DB_S_COLUMNTYPEMISMATCH | Some columns cannot be converted during the copy operation because of type-conversion incompatibilities. |
DB_S_COMMANDREEXECUTED | The command was re-executed. |
DB_S_DELETEDROW | A row handle refers to a previously deleted row. |
DB_S_DIALECTIGNORED | The language of the command was ignored; translated command returned. |
DB_S_ENDOFROWSET | The end of the current row set was encountered. |
DB_S_ERRORSINTREE | An error occurred in the validation tree. |
DB_S_ERRORSOCCURRED | An unspecified error occurred. |
DB_S_ERRORSRETURNED | Errors were encountered and returned. |
DB_S_GOALCHANGED | The current goal was changed to an unsupported value. |
DB_S_LOCKUPGRADED | A record lock was upgraded. |
DB_S_MULTIPLECHANGES | The requested change affects multiple data source rows. |
DB_S_NONEXTROWSET | End of multiple return row sets reached. |
DB_S_NORESULT | End of results reached. |
DB_S_PARAMUNAVAILABLE | The specified parameter is invalid. |
DB_S_PROPERTIESCHANGED | The properties of the object were changed successfully. |
Warning Results | |
DB_S_ROWLIMITEXCEEDED | The number of requested rows is greater than the number of active rows that the Rowset object supports. |
DB_S_STOPLIMITREACHED | Execution of a command was halted because of a resource limit; the results returned are incomplete. |
DB_S_TOOMANYCHANGES | Too many changes were encountered; data must be refreshed. |
DB_S_TYPEINFOOVERRIDDEN | The type of the parameter was overridden. |
DB_S_UNWANTEDPHASE | Notifications for this phase are no longer desired. |
DB_S_UNWANTEDREASON | Notifications for this phase are no longer desired for a specific reason. |
Error Results | |
DB_E_ABORTLIMITREACHED | The command was aborted because of resource limitations; no results returned. |
DB_E_ALREADYINITIALIZED | The data source was previously initialized. |
DB_E_BADACCESSORFLAGS | The Accessor flag is not valid. |
DB_E_BADACCESSORHANDLE | The Accessor handle is not valid. |
DB_E_BADACCESSORTYPE | The Accessor specified is invalid. |
DB_E_BADBINDINFO | The binding information is not valid. |
DB_E_BADBOOKMARK_ | The bookmark is not valid. |
DB_E_BADCHAPTER | The chapter specified is not valid. |
DB_E_BADCOLUMNID_ | The column ID specified is not valid. |
DB_E_BADCONVERTFLAG_ | The conversion flag specified is not valid. |
DB_E_BADCOPY | An error was encountered while copying. |
DB_E_BADDYNAMICERRORID_ | The DynamicError ID specified is not valid. |
DB_E_BADHRESULT_ | The HRESULT value specified is not valid. |
DB_E_BADID_ | The table ID value specified is not valid. |
DB_E_BADLOCKMODE_ | The lock mode specified is not valid. |
DB_E_BADLOOKUPID_ | The lookup ID specified is not valid. |
DB_E_BADORDINAL_ | The column specified is not valid. |
DB_E_BADPARAMETERNAME_ | The specified parameter name is not valid. |
DB_E_BADPRECISION_ | The precision value specified is not valid. |
DB_E_BADPROPERTYVALUE_ | The property value is not valid. |
Error Results | |
DB_E_BADRATIO_ | The ratio specified is not valid (greater than 1 or undefined). |
DB_E_BADRECORDNUM_ | The record number specified is not valid. |
DB_E_BADREGIONHANDLE_ | The region handle specified is not valid. |
DB_E_BADROWHANDLE_ | The row handle is not valid. |
DB_E_BADSCALE_ | The scale value specified is not valid. |
DB_E_BADSOURCEHANDLE_ | The source handle specified is not valid. |
DB_E_BADSTARTPOSITION_ | The offset position specified is past the end or before the beginning of the row set; rows not retrieved. |
DB_E_BADSTATUSVALUE_ | The status flag specified is not valid. |
DB_E_BADSTORAGEFLAG_ | The storage flag specified is not valid. |
DB_E_BADSTORAGEFLAGS_ | The storage flags specified are not valid._ |
DB_E_BADTYPE_ | The type specified is not valid. |
DB_E_BADTYPENAME_ | The type name specified is not valid. |
DB_E_BADVALUES_ | The value specified is not valid. |
DB_E_BOOKMARKSKIPPED_ | No row was found that matched the bookmark. |
DB_E_BYREFACCESSORNOTSUPPORTED_ | Cannot pass Accessor by reference for this data provider. |
DB_E_CANCELED_ | The command was canceled; changes not saved. |
DB_E_CANNOTFREE_ | Cannot deallocate this memory. |
DB_E_CANNOTRESTART_ | Cannot restart the new row set. |
DB_E_CANTCANCEL_ | Cannot stop the current command. |
DB_E_CANTCONVERTVALUE_ | Cannot convert the specified value correctly. |
DB_E_CANTFETCHBACKWARDS_ | Cannot retrieve the row set rows backwards. |
DB_E_CANTSCROLLBACKWARDS_ | The row set cannot scroll backwards. |
DB_E_CANTTRANSLATE_ | Cannot translate the current command tree. |
DB_E_CHAPTERNOTRELEASED_ | The chapter was not released. |
DB_E_CONCURRENCYVIOLATION_ | A concurrency violation was encountered. |
DB_E_COSTLIMIT_ | When attempting to optimize the query, the cost constraints could not be met. |
DB_E_DATAOVERFLOW_ | A command value caused an overflow. |
DB_E_DELETEDROW_ | The row handle points to a deleted row. |
Error Results | |
DB_E_DIALECTNOTSUPPORTED_ | The language of the command is not supported. |
DB_E_DUPLICATECOLUMNID_ | A column was duplicated. |
DB_E_DUPLICATEDATASOURCE_ | The data source name is already in use. |
DB_E_DUPLICATEINDEXID_ | The index specified is already in use. |
DB_E_DUPLICATETABLEID_ | The table specified already exists. |
DB_E_ERRORSINCOMMAND_ | Errors were encountered in the command. |
DB_E_ERRORSOCCURRED_ | An unspecified error occurred. |
DB_E_GOALREJECTED_ | The goal specified was not valid; current goal unchanged. |
DB_E_INDEXINUSE_ | The index specified is already opened. |
DB_E_INTEGRITYVIOLATION_ | A column value violated integrity constraints for that object. |
DB_E_INVALID_ | Cannot use bookmarks on this row set. |
DB_E_INVALIDTRANSITION_ | The transition specified is not valid. |
DB_E_LIMITREJECTED_ | Cost limits specified were not valid. |
DB_E_MAXPENDCHANGESEXCEEDED_ | The maximum number of pending changes has been exceeded. |
DB_E_MULTIPLESTATEMENTS_ | Multiple statement commands are not supported. |
DB_E_MULTIPLESTORAGE_ | More than one storage object opened concurrently. |
DB_E_NEWLYINSERTED_ | Cannot establish the identity of the new rows. |
DB_E_NOAGGREGATION_ | This object does not support aggregation. |
DB_E_NOCOMMAND_ | The command has not been specified. |
DB_E_NOINDEX_ | The specified index is not valid. |
DB_E_NOLOCALE_ | The locale ID specified is not valid. |
DB_E_NONCONTIGUOUSRANGE_ | The set of rows specified are not contiguous. |
DB_E_NOQUERY_ | The query was not defined. |
DB_E_NOTABLE_ | The table specified does not exist. |
DB_E_NOTAREFERENCECOLUMN_ | The column does not contain a bookmark or chapter identifier. |
DB_E_NOTASUBREGION_ | The region specified is not a valid subregion. |
DB_E_NOTFOUND_ | Cannot find the specified key value. |
DB_E_NOTPREPARED_ | Cannot prepare the specified command. |
DB_E_NOTREENTRANT_ | A method was called while another was still executing. |
Error Results | |
DB_E_NOTSUPPORTED_ | The method specified is not supported. |
DB_E_NULLACCESSORNOTSUPPORTED_ | Cannot pass NULL value Accessor to this data provider. |
DB_E_OBJECTOPEN_ | Operation performed on an object that was not opened. |
DB_E_PARAMNOTOPTIONAL_ | A value was not specified for a required parameter. |
DB_E_PARAMUNAVAILABLE_ | The parameter specified is not available. |
DB_E_PENDINGCHANGES_ | Changes are pending on an unreferenced row. |
DB_E_PENDINGINSERT_ | Cannot perform the pending insert. |
DB_E_READONLYACCESSOR_ | Accessor is read-only; write invalid. |
DB_E_ROWLIMITEXCEEDED_ | Adding this row exceeds the number of active rows for this row set. |
DB_E_ROWSETINCOMMAND_ | Cannot copy a command that contains row sets. |
DB_E_ROWSNOTRELEASED_ | The current row handles were not released before retrieving new rows. |
DB_E_SCHEMAVIOLATION_ | The values supplied are inconsistent with the data source schema. |
DB_E_TABLEINUSE_ | The table specified is already opened. |
DB_E_UNSUPPORTEDCONVERSION_ | Cannot perform the requested type conversion. |
DB_E_WRITEONLYACCESSOR_ | The specified Accessor can only be written. |
DB_SEC_E_AUTH_FAILED_ | Security error; data source access authorization was not successful. |
DB_SEC_E_PERMISSIONDENIED | Permission denied because of a security violation. |
Day 21 explains how to integrate error handling into OLE DB applications. You learned how to implement basic error-handling techniques and how to check the HRESULT of a method with the SUCCEEDED and FAILED macros to determine whether the method executed correctly. Then you learned how to use the ISupportErrorInfo interface to determine whether an OLE DB object supports extended error information.
You used the IErrorRecords and ISQLErrorInfo methods to create the DispErrorInfo procedure, which can display extended error information for any OLE DB object.
This section answers some common questions related to today's
topics.
Should my application look for and try to interpret specific HRESULT values? | |
If you look at the OLE DB error information, you will see that as each method is defined, the most common HRESULT values that the method can return are listed. A useful exercise is to try to interpret certain warning result values. You can be assured only that an OLE DB provider supports the methods and interfaces that are required. If you attempt to access an optional interface, you will need to be sure that your application can still function if the data provider doesn't support that interface. | |
Is there any way other than checking the HRESULT value of each method call to add error handling to my OLE DB application? | |
Unfortunately, no. To ensure the highest degree of error checking in your applications, you must check each method's HRESULT value. You must realize that one failed method can cause a cascading error effect. Again, the best technique is to design your applications to be robust so that they offer only the functionality provided by the OLE DB data provider. A robust application is one that can handle all error conditions without crashing for the end user. As an application developer, you are responsible for handling all errors that your application might generate. |
The Workshop quiz questions test your understanding of today's material. (The answers appear in Appendix F, "Answers.") The exercises encourage you to apply the information you learned today to real-life situations.
© Copyright, Sams Publishing. All rights reserved.