Skip to content

Commit d7f66fd

Browse files
author
Hemant Dangi
committed
Added support for mysql_options4 connection attributes.
1 parent 2066050 commit d7f66fd

14 files changed

+189
-25
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ GA 1.1.4 -
3131
"sslVerify"(boolean), "sslCRL" and "sslCRLPath"(string). (Bug#18461451)
3232
- Methods returning driver version information are now parametrized, and those
3333
parameters take their values from cmake config (Bug#14680878/66975)
34+
- Added MYSQL_OPT_CONNECT_ATTR_ADD connection option accepting std::map
35+
argument and calls mysql_options4(). (Bug#18803313)
3436

3537
- Built against libmysql 5.6.
3638

cppconn/connection.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3737
namespace sql
3838
{
3939

40-
41-
typedef boost::variant<int, double, bool, sql::SQLString > ConnectPropertyVal;
40+
typedef boost::variant<int, double, bool, sql::SQLString, std::map< sql::SQLString, sql::SQLString > > ConnectPropertyVal;
4241

4342
typedef std::map< sql::SQLString, ConnectPropertyVal > ConnectOptionsMap;
4443

cppconn/exception.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,28 @@ struct CPPCONN_PUBLIC_FUNC NonScrollableException : public SQLException
123123
NonScrollableException(const std::string& reason) : SQLException(reason, "", 0) {}
124124
};
125125

126+
struct CPPCONN_PUBLIC_FUNC SQLUnsupportedOptionException : public SQLException
127+
{
128+
SQLUnsupportedOptionException(const SQLUnsupportedOptionException& e, const std::string conn_option) :
129+
SQLException(e.what(), e.sql_state, e.errNo),
130+
option(conn_option )
131+
{}
132+
133+
SQLUnsupportedOptionException(const std::string& reason, const std::string conn_option) :
134+
SQLException(reason, "", 0),
135+
option(conn_option )
136+
{}
137+
138+
const char *getConnectionOption() const
139+
{
140+
return option.c_str();
141+
}
142+
143+
~SQLUnsupportedOptionException() throw () {};
144+
protected:
145+
const std::string option;
146+
};
147+
126148
} /* namespace sql */
127149

128150
#endif /* _SQL_EXCEPTION_H_ */

driver/mysql_connection.cpp

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3030
#include <memory>
3131
#include <sstream>
3232
#include <stdio.h>
33+
#include <map>
3334
#ifdef HAVE_STDINT_H
3435
#include <stdint.h>
3536
#endif
@@ -266,9 +267,13 @@ bool process_connection_option(ConnectOptionsMap::const_iterator &option,
266267
err.append(option->first).append(" is not of expected type");
267268
throw sql::InvalidArgumentException(err);
268269
}
269-
proxy->options(static_cast<sql::mysql::MySQL_Connection_Options>(options_map[i].value),
270+
try {
271+
proxy->options(static_cast<sql::mysql::MySQL_Connection_Options>(options_map[i].value),
270272
*value);
271-
273+
} catch (sql::InvalidArgumentException& e) {
274+
std::string errorOption(options_map[i].key);
275+
throw ::sql::SQLUnsupportedOptionException(e.what(), errorOption);
276+
}
272277
return true;
273278
}
274279
}
@@ -345,7 +350,7 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
345350
const sql::SQLString * p_s;
346351
bool opt_reconnect = false;
347352
bool opt_reconnect_value = false;
348-
bool client_doesnt_support_exp_pwd = false;
353+
int client_exp_pwd = false;
349354
bool secure_auth= true;
350355

351356

@@ -506,20 +511,15 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
506511
/* Not sure it is really needed */
507512
uri.setProtocol(NativeAPI::PROTOCOL_PIPE);
508513
} else if (!it->first.compare("OPT_CAN_HANDLE_EXPIRED_PASSWORDS")) {
509-
/* We need to know client version at runtime */
510-
long client_ver= proxy->get_client_version();
511-
if (proxy->get_client_version() < 50610) {
512-
// TODO: I think we should throw a warning here
513-
/* We only need this flag set if application has said it supports expired
514-
password mode */
515-
client_doesnt_support_exp_pwd= true;
516-
} else {
517-
if (!(p_b = boost::get< bool >(&it->second))) {
518-
throw sql::InvalidArgumentException("No bool value passed for "
519-
"OPT_CAN_HANDLE_EXPIRED_PASSWORDS");
520-
}
521-
/* We do not care here about server version */
522-
proxy->options(MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, (const char*)p_b);
514+
if (!(p_b = boost::get< bool >(&it->second))) {
515+
throw sql::InvalidArgumentException("No bool value passed for "
516+
"OPT_CAN_HANDLE_EXPIRED_PASSWORDS");
517+
}
518+
try {
519+
client_exp_pwd= proxy->options(MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, (const char*)p_b);
520+
} catch (sql::InvalidArgumentException& e) {
521+
std::string errorOption("MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS");
522+
throw ::sql::SQLUnsupportedOptionException(e.what(), errorOption);
523523
}
524524
} else if (!it->first.compare("postInit")) {
525525
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
@@ -533,6 +533,19 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
533533
} else {
534534
throw sql::InvalidArgumentException("No bool value passed for useLegacyAuth");
535535
}
536+
} else if (!it->first.compare("OPT_CONNECT_ATTR_ADD")) {
537+
const std::map< sql::SQLString, sql::SQLString > *conVal=
538+
boost::get< std::map< sql::SQLString, sql::SQLString > >(&it->second);
539+
std::map< sql::SQLString, sql::SQLString >::const_iterator conn_attr_it;
540+
for (conn_attr_it = conVal->begin(); conn_attr_it != conVal->end(); conn_attr_it++) {
541+
try {
542+
proxy->options(MYSQL_OPT_CONNECT_ATTR_ADD, conn_attr_it->first, conn_attr_it->second);
543+
} catch (sql::InvalidArgumentException& e) {
544+
std::string errorOption("MYSQL_OPT_CONNECT_ATTR_ADD");
545+
throw ::sql::SQLUnsupportedOptionException(e.what(), errorOption);
546+
}
547+
}
548+
536549
/* If you need to add new integer connection option that should result in
537550
calling mysql_optiong - add its mapping to the intOptions array
538551
*/
@@ -575,9 +588,20 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
575588

576589
proxy->use_protocol(uri.Protocol());
577590

578-
proxy->options(MYSQL_SECURE_AUTH, &secure_auth);
591+
try {
592+
proxy->options(MYSQL_SECURE_AUTH, &secure_auth);
593+
} catch (sql::InvalidArgumentException& e) {
594+
std::string errorOption("MYSQL_SECURE_AUTH");
595+
throw ::sql::SQLUnsupportedOptionException(e.what(), errorOption);
596+
}
597+
598+
try {
599+
proxy->options(MYSQL_SET_CHARSET_NAME, defaultCharset.c_str());
600+
} catch (sql::InvalidArgumentException& e) {
601+
std::string errorOption("MYSQL_SET_CHARSET_NAME");
602+
throw ::sql::SQLUnsupportedOptionException(e.what(), errorOption);
603+
}
579604

580-
proxy->options(MYSQL_SET_CHARSET_NAME, defaultCharset.c_str());
581605

582606
if (ssl_used) {
583607
/* According to the docs, always returns 0 */
@@ -607,7 +631,7 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
607631
int native_error= proxy->errNo();
608632

609633
if (native_error == ER_MUST_CHANGE_PASSWORD_LOGIN
610-
&& client_doesnt_support_exp_pwd) {
634+
&& client_exp_pwd) {
611635

612636
native_error= deCL_CANT_HANDLE_EXP_PWD;
613637
error_message= "Your password has expired, but your instance of"
@@ -626,7 +650,12 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
626650
}
627651

628652
if (opt_reconnect) {
629-
proxy->options(MYSQL_OPT_RECONNECT, (const char *) &opt_reconnect_value);
653+
try {
654+
proxy->options(MYSQL_OPT_RECONNECT, (const char *) &opt_reconnect_value);
655+
} catch (sql::InvalidArgumentException& e) {
656+
std::string errorOption("MYSQL_OPT_RECONNECT");
657+
throw ::sql::SQLUnsupportedOptionException(e.what(), errorOption);
658+
}
630659
}
631660

632661
setAutoCommit(true);

driver/nativeapi/libmysql_dynamic_proxy.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,29 @@ LibmysqlDynamicProxy::options(MYSQL * mysql, enum mysql_option option, const voi
392392
{
393393
ptr2mysql_options ptr2_options = symbol_safe_cast<ptr2mysql_options>(GetProcAddr("mysql_options"));
394394

395-
return (*ptr2_options)(mysql, option, arg);
395+
if ((*ptr2_options)(mysql, option, arg)) {
396+
throw sql::InvalidArgumentException("Unsupported option provided to mysql_options()");
397+
} else {
398+
return 0;
399+
}
400+
}
401+
/* }}} */
402+
403+
404+
/* {{{ LibmysqlDynamicProxy::options() */
405+
int
406+
LibmysqlDynamicProxy::options(MYSQL * mysql, enum mysql_option option, const void *arg1, const void *arg2)
407+
{
408+
ptr2mysql_options4 ptr2_options = symbol_safe_cast<ptr2mysql_options4>(GetProcAddr("mysql_options4"));
409+
if (ptr2_options != NULL) {
410+
if (((*ptr2_options)(mysql, option, arg1, arg2))) {
411+
throw sql::InvalidArgumentException("Unsupported option provided to mysql_options4()");
412+
} else {
413+
return 0;
414+
}
415+
} else {
416+
throw ::sql::MethodNotImplementedException("::mysql_options4()");
417+
}
396418
}
397419
/* }}} */
398420

driver/nativeapi/libmysql_dynamic_proxy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class LibmysqlDynamicProxy : public sql::mysql::util::LibraryLoader, public IMyS
111111

112112
int options (MYSQL *, enum mysql_option, const void *);
113113

114+
int options (MYSQL *, enum mysql_option, const void *, const void *);
115+
114116
int ping(MYSQL *);
115117

116118
int query(MYSQL *, const char *);

driver/nativeapi/libmysql_static_proxy.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2727

2828
#include "libmysql_static_proxy.h"
2929

30+
#include <cppconn/exception.h>
3031

3132
namespace sql
3233
{
@@ -279,7 +280,28 @@ int
279280
LibmysqlStaticProxy::options(MYSQL * mysql, enum mysql_option option, const void *arg)
280281
{
281282
// in 5.0 mysql_options's 3rd parameter is "const char *"
282-
return ::mysql_options(mysql, option, static_cast<const char *>(arg));
283+
if ((::mysql_options(mysql, option, static_cast<const char *>(arg)))) {
284+
throw sql::InvalidArgumentException("Unsupported option provided to mysql_options()");
285+
} else {
286+
return 0;
287+
}
288+
}
289+
/* }}} */
290+
291+
292+
/* {{{ LibmysqlStaticProxy::options4() */
293+
int
294+
LibmysqlStaticProxy::options(MYSQL * mysql, enum mysql_option option, const void *arg1, const void *arg2)
295+
{
296+
#if MYSQL_VERSION_ID >= 50606
297+
if ((::mysql_options4(mysql, option, static_cast<const char *>(arg1), static_cast<const char *>(arg2)))) {
298+
throw sql::InvalidArgumentException("Unsupported option provided to mysql_options4()");
299+
} else {
300+
return 0;
301+
}
302+
#else
303+
throw ::sql::MethodNotImplementedException("::mysql_options4()");
304+
#endif
283305
}
284306
/* }}} */
285307

driver/nativeapi/libmysql_static_proxy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class LibmysqlStaticProxy : public IMySQLCAPI, public ::sql::mysql::util::Single
128128

129129
int options(MYSQL *, enum mysql_option, const void *);
130130

131+
int options(MYSQL *, enum mysql_option, const void *, const void *);
132+
131133
int ping(MYSQL *);
132134

133135
int query(MYSQL *, const char *);

driver/nativeapi/mysql_client_api.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ typedef my_ulonglong (STDCALL *ptr2mysql_num_rows)(MYSQL_RES *);
9191

9292
typedef int (STDCALL *ptr2mysql_options)(MYSQL *, enum mysql_option, const void *);
9393

94+
typedef int (STDCALL *ptr2mysql_options4)(MYSQL *, enum mysql_option, const void *, const void *);
95+
9496
typedef int (STDCALL *ptr2mysql_query)(MYSQL *, const char *);
9597

9698
typedef int (STDCALL *ptr2mysql_ping)(MYSQL *);
@@ -216,6 +218,8 @@ class IMySQLCAPI
216218

217219
virtual int options(MYSQL *, enum mysql_option option , const void *arg) = 0;
218220

221+
virtual int options(MYSQL *, enum mysql_option option , const void *arg1, const void *arg2) = 0;
222+
219223
virtual int ping(MYSQL *) = 0;
220224

221225
virtual int query(MYSQL *, const char *) = 0;

driver/nativeapi/mysql_native_connection_wrapper.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,16 @@ MySQL_NativeConnectionWrapper::options(::sql::mysql::MySQL_Connection_Options op
244244
}
245245

246246

247+
/* {{{ MySQL_NativeConnectionWrapper::options(SQLString &, SQLString &) */
248+
int
249+
MySQL_NativeConnectionWrapper::options(::sql::mysql::MySQL_Connection_Options option,
250+
const ::sql::SQLString &key, const ::sql::SQLString &value)
251+
{
252+
return api->options(mysql, static_cast< mysql_option >(option), key.c_str(), value.c_str());
253+
}
254+
/* }}} */
255+
256+
247257
/* {{{ MySQL_NativeConnectionWrapper::query() */
248258
int
249259
MySQL_NativeConnectionWrapper::query(const SQLString & stmt_str)

0 commit comments

Comments
 (0)