In the preceding sections you learned that whenever a DBTools.h++ object changes status to something other than RWDBStatus::ok, its installed error handler is invoked. We examined some very simple error handlers. Here's another which is equally simple, but which has quite a different effect:
void exHandler(const RWDBStatus& status) { status.raise(); }
The raise()method of RWDBStatus throws an exception of type RWExternalErr, using the macro RWTHROW. If your compiler supports exceptions, this macro is defined as follows:
#define RWTHROW(a) throw a
and it throws a true exception. If your compiler does not fully support exceptions, it calls an error handler with prototype:
void errHandler(const RWxmsg&);
The default error handler aborts the program. You can change the default handler with the function:
typedef void (*rwErrHandler)(const RWxmsg&); rwErrHandler rwSetErrHandler(rwErrHandler);
In the DBTools.h++ error model, the use of C++ exceptions is optional, and is under your application's control. If you were to install the error handler above into the RWDBManager, you would put your application in a position to use the exception mechanism defined by the C++ standard. How would this affect the example?
// Error Handling - version 4 RWDBManager::setErrorHandler (exHandler); . . . RWDBReader reader = anotherTable.reader(); while (reader()) { try { RWCString s; float f; reader >> s >> f; // process s and f } catch(RWxmsg x) { cout << "Error processing anotherTable: " << x.why() << endl; } }
Once again, our error handling is the same: print a message, exit the loop, and continue. This time we have retained context information, once again at the expense of some inline code, but the inline code is in its own block.
Which technique is best? There is no clear-cut answer; it depends on what fits best with the rest of your application. We recommend that you choose the method you prefer and use it consistently.
With earlier versions of DBTools.h++, some applications experienced problems when employing user-defined callbacks and C++ exception handling capabilities. These problems seemed specific to the DBTools.h++ access libraries for MS SQL Server and Sybase Client-Library. If you were using user-defined callbacks with these access libraries and a C++ exception was thrown, the process of unwinding the call stack would leave your application in an indeterminate state, in other words, a crash. In general, it was not safe to throw an exception within a C library.
This problem has been corrected. The DBTools.h++ library is now exception safe, and you can use user-defined callbacks at will. The correction was made internally with no change to the API, and no known side effects for existing applications.
©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.