Bug #29271 setting connection options is broken
Submitted: 21 Jun 2007 14:37 Modified: 22 Jun 2007 13:47
Reporter: Axel Schwenke Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL++ Severity:S1 (Critical)
Version:2.2.3 OS:Any
Assigned to: CPU Architecture:Any

[21 Jun 2007 14:37] Axel Schwenke
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.
[22 Jun 2007 13:47] Axel Schwenke
The bug has been fixed by the maintainer.