Class RWDBStatus is an important component of the DBTools.h++ error model. Each RWDBStatus instance encapsulates the error state of an object or operation. Here is a partial listing of the definition of class RWDBStatus:
class RWDBStatus { public: enum ErrorCode { . . . }; . . . void raise() const; RWBoolean isValid() const; . . . ErrorCode errorCode() const; RWCString message() const; long vendorError1() const; long vendorError2() const; RWCString vendorMessage1() const; RWCString vendorMessage2() const; };
Notice that the ErrorCode enumeration is scoped within class RWDBStatus. To avoid polluting the global name space, all DBTools.h++ enums are scoped within classes. To refer to a member of the enumeration outside the scope of class RWDBStatus, use the scoping operator ::, as in RWDBStatus::ok, for example. Appendix A lists the possible RWDBStatus::ErrorCode values.
A valid object, or a successful operation, is represented by an ErrorCode of RWDBStatus::ok. An RWDBStatus instance whose ErrorCode is vendorLib, serverError, or serverMessage reflects a database error or error of some kind, and contains database-dependent information. Other RWDBStatus instances represent errors generated by DBTools.h++ itself.
All DBTools.h++ classes that interact with a database have a status, accessible through a status()method. Classes that do not have a status include:
the concrete classes, including RWDBBlob, RWDBDateTime, RWDecimalPortable, RWDBDuration, and RWCString;
the classes related to the bulk read and write mechanism, including RWDBBinaryVector, RWDBStringVector, RWDBDateVector, RWDBStringVectorElement, RWDBBinaryVectorElement, and RWDBVendorDate;
and the classes RWDBAssignment, RWDBCriterion, RWDBExpr, RWDBManager, RWDBPhraseBook, and RWDBTracer.
In classes that have status, certain member functions generate errors that do not affect the object itself. For example, the drop() method of RWDBTable succeeds or fails without affecting the RWDBTable itself. This type of method returns an RWDBStatus object instead. Errors encountered by all other member functions result in a change of status in the object itself.
Member functions that interact with a database either:
Return an RWDBStatus object,
Return an object that has a status, or
Change the status of the object through which the function was invoked when an error occurs.
Returning to our earlier example, we could do this:
// Error Handling - Version 1 RWDBReader reader = anotherTable.reader(); while (reader()) { RWCString s; float f; reader >> s >> f; if (reader.isValid()) {//1 . . // process s and f . } else { // handle the error cout << "Error reading anotherTable: " << reader.status().message() << endl; } }
On //1, the isValid() function, which in general checks the RWDBStatus of the object through which it was invoked, checks the status of the reader. This inline error checking technique has some advantages. For one thing, it is simple. Also, trapping an error close to the point where it occurs gives an application more context with which to handle the error. Here we are able to identify what was going on at the time the error occurred, that is, the application was reading anotherTable.
The error handling in this example is rudimentary: print a message, exit the processing loop, and continue. The loop is exited because the reader()call returns 0 when the reader's status is not ok.
This type of error handling is adequate in some contexts, but not in others. Inline error checking clutters up the original code, and distracts both the programmer and the reader of the code from its main purpose. Section 5.3 presents a less disruptive, more centralized method of reporting errors using error handlers.
©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.