Description:
Setting connection options with mysqlpp::Connection::set_option(...) is broken for all options except opt_multi_statements.
The various Connection::set_option() members contain code like this:
if (connected() || connecting_) {
switch (option) {
case opt_init_command:
return set_option_impl(MYSQL_INIT_COMMAND, arg);
...
default:
return bad_option(option, opt_type_string);
}
}
else {
pending_options_.push_back(OptionInfo(option, arg));
return false;
}
so options are only applied with set_option_impl() (basically a call to mysql_options()) if the connection is already established. Howeverall options except opt_multi_statements should be set immediately. If the connection is already established, a warning should be given.
If there was no connection established, the options are queued and set later by calling apply_pending_options() in Connection::connect():
// Establish connection
if (mysql_real_connect(&mysql_, host, user, passwd, db, port,
socket_name, client_flag)) {
unlock();
success_ = is_connected_ = true;
apply_pending_options();
if (db && db[0]) {
// Also attach to given database
success_ = select_db(db);
}
}
else {
unlock();
success_ = is_connected_ = false;
if (throw_exceptions()) {
throw ConnectionFailed(error());
}
}
Again mysql_options() is called after mysql_real_connect() so the options will not take effect.
According to the MySQL manual http://dev.mysql.com/doc/refman/5.0/en/mysql-options.html mysql_options() must be called after mysql_init() (this is done in the Connection constructor) but before mysql_real_connect().
How to repeat:
Example C++ code:
using namespace mysqlpp;
Connection con(false);
con.set_option(opt_read_timeout, (unsigned)10);
con.connect("test");
this will set MYSQL_OPT_READ_TIMOUT in the associated MYSQL object, but only after calling mysql_real_connect(). So this option will not take effect.
Suggested fix:
The set_option() accessors should set all connection options except opt_multi_statements immediately and give a warning if any such option is set when a connection is already established.
The only option to push back after mysql_real_connect() is opt_multi_statements. This also simplifies the handling of pending options.