Error Handling
As we know, even valid SQL statements don’t always succeed when executed. Problems such as loss of connectivity, invalid data, and myriad other errors can cause an otherwise good SQL statement to fail. Fortunately, checking the success or failure of an Open SQL execution is straightforward: you follow the same error model used in the standard API of the DB Interface Module. (See
Chapter 6, The Error Model.)
With Open SQL, any error that occurs during execution causes the
RWDBOSql instance to become invalid, and its status is changed to reflect the error. However, the
RWDBOSql instance may still be reused; it remains invalid only until the next successful execution.
Let’s see how error handling works with Open SQL. Using the error model of the DB Interface Module, we can easily add in-line error checking to the previous code sample:
RWDBConnection aConn = aDb.connection(); // 1
RWDBOSql anOSql(“INSERT INTO MYTABLE VALUES(10)”); // 2
anOSql.execute(aConn); // 3
// Did the execution fail?
if ( !anOSql.isValid() ) { // 4
// It failed. Print out the error message.
// someOstream is an ostream or std::ostream, such as
// cout or cerr (or std::cout, std::cerr)
someOstream << “Error: “
<< anOSql.status().message() // 5
<< endl;
}
In
//1 -
//3, we execute the statement as in the previous example. On
//4, we use the
isValid() method on the
RWDBOSql; here
isValid() returns
false if the execution of the SQL statement fails. On
//5, we use the
status() method to return an
RWDBStatus that contains information about the error, such as a printable error message, and error codes. Although the
RWDBOSql is invalid at this point, we can choose to reinvoke
execute(). If the re-execution succeeds, the
RWDBOSql becomes valid again, so that calling
isValid() on it returns
true.