Thanks a lot for the recipe! But the asynchronous MySQL API I'm working on is based on Asio, which uses Boost.System for error handling. Boost.System provides a unified method to handle errors with both traditional error code paradigm and the exception paradigm. Thus, there may be code like this: connector.async_query( "SHOW DATABASES", handle_query ); void handle_query( boost::system::error_code const& ec ) { if( ec ) { std::cerr << boost::format( "Query error: %1% - %2%" ) % ec.value() % ec.message() << std::endl; } else { // ... } } The ec.message() call above is redirected to the message() method of the user defined error_category class (amysql::client_category in my case) with an error code (ONLY!). Currently, I use a boost::thread_specific_ptrstd::string to store the last MySQL error message, and in the amysql::client_category::message() method, the error code parameter is ignored, and just return the thread specific last error message string. The pitfall here is that an error_code object should never be stored for later usage, since the thread specific last error message would be changed whenever a new error occurred. I think Boost.System should allow user to pass into a function object instead of a single error code to the error_category::message() function, so that user can have better control on error message generation policies. Cheers Cheng Emil Dotchevski:
On Mon, Feb 23, 2009 at 2:33 AM, Lian Cheng
wrote: On Fri, 20 Feb 2009 09:36:53 +0100, Lian Cheng
wrote: Isn't there a list of error numbers and error strings MySQL uses? I ask as calling error_category::message() should also return an error string even if no MySQL connection is used? Unfortunately, no. As I've mentioned, the error strings MySQL uses are
Boris Schaeling: printf format strings, such as:
Using unsupported buffer type: %d (parameter: %d)
And you always need an active MySQL connection handle to obtain the full error message by calling mysql_error(). And you can never get the message back once you close the connection:
MYSQL* conn = mysql_init( 0 ); // do something causes an error. mysql_close( conn ); printf( "error: %s", mysql_error( conn ) ); // Messed up.
Boost Exception can be used to transport anything in an exception object. You can transport error codes as well as error messages:
#include
typedef boost::error_info
mysql_error_code; typedef boost::error_info mysql_error_string; struct mysql_err: std::exception, boost::exception { }; .... if( int error=mysql_query(conn,....) ) throw mysql_err() << mysql_error_code(error) << mysql_error_string(mysql_error(conn));
Alternatively, if you use shared_ptr to manage the lifetime of the MYSQL connection, as in:
boost::shared_ptr<MYSQL> conn( mysql_init(0), mysql_close );
you can use an exception object to keep the connection afloat:
typedef boost::error_info
mysql_error_code; typedef boost::error_info mysql_conn; struct mysql_err: std::exception, boost::exception { }; .... if( int error=mysql_query(conn,....) ) throw mysql_err() << mysql_error_code(error) << mysql_conn(conn);
Now, when you catch mysql_err, you can talk to mysql to get the error message:
catch( mysql_err & x ) { boost::shared_ptr<MYSQL> conn=*boost::get_error_info
(x); char const * msg=mysql_error(conn.get()); .... } Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode