Skip to content

Commit 491bc70

Browse files
author
лаврин
committed
1) uri parsing moved to a separate class and its syntax is extended a bit - introduced host separator ([]) mainly to makemore clear syntax for IPv6 addresses.
1 parent e330c14 commit 491bc70

File tree

10 files changed

+652
-79
lines changed

10 files changed

+652
-79
lines changed

driver/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ SET(MYSQLCPPCONN_SOURCES
112112
mysql_statement.cpp
113113
mysql_util.cpp
114114
mysql_warning.cpp
115+
mysql_uri.cpp
115116
nativeapi/mysql_client_api.cpp
116117
nativeapi/library_loader.cpp
117118
nativeapi/mysql_native_driver_wrapper.cpp
@@ -142,6 +143,7 @@ IF(WIN32)
142143
mysql_statement.h
143144
mysql_util.h
144145
mysql_warning.h
146+
mysql_uri.h
145147
nativeapi/mysql_client_api.h
146148
nativeapi/mysql_native_driver_wrapper.h
147149
nativeapi/native_driver_wrapper.h

driver/mysql_connection.cpp

Lines changed: 53 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
4040

4141
#include "mysql_connection_options.h"
4242
#include "mysql_util.h"
43+
#include "mysql_uri.h"
4344

4445
/*
4546
* _WIN32 is defined by 64bit compiler too
@@ -106,7 +107,9 @@ MySQL_Connection::MySQL_Connection(Driver * _driver,
106107
const sql::SQLString& hostName,
107108
const sql::SQLString& userName,
108109
const sql::SQLString& password)
109-
: driver(_driver), proxy(&_proxy), intern(NULL)
110+
: driver (_driver),
111+
proxy (&_proxy),
112+
intern (NULL)
110113
{
111114
sql::ConnectOptionsMap connection_properties;
112115
connection_properties["hostName"] = hostName;
@@ -203,20 +206,16 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
203206
CPP_ENTER_WL(intern->logger, "MySQL_Connection::init");
204207

205208
intern->is_valid = true;
206-
bool protocol_tcp = true;
207-
sql::SQLString host;
208-
sql::SQLString socket_or_pipe;
209-
unsigned int port = 3306;
210209

211-
sql::SQLString hostName;
210+
MySQL_Uri uri;
211+
212212
sql::SQLString userName;
213213
sql::SQLString password;
214-
sql::SQLString schema;
215214
sql::SQLString defaultCharset("utf8");
216215
sql::SQLString characterSetResults("utf8");
217216

218217
sql::SQLString sslKey, sslCert, sslCA, sslCAPath, sslCipher;
219-
bool ssl_used = false, schema_used = false;
218+
bool ssl_used = false;
220219
int flags = CLIENT_MULTI_RESULTS;
221220

222221
const int * p_i;
@@ -225,15 +224,23 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
225224
bool opt_reconnect = false;
226225
bool opt_reconnect_value = false;
227226

228-
sql::ConnectOptionsMap::const_iterator it = properties.begin();
229-
for (; it != properties.end(); ++it) {
230-
if (!it->first.compare("hostName")) {
231-
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
232-
hostName = *p_s;
233-
} else {
234-
throw sql::InvalidArgumentException("No string value passed for hostName");
235-
}
236-
} else if (!it->first.compare("userName")) {
227+
228+
/* Values set in properties individually should have priority over those
229+
we restore from Uri */
230+
sql::ConnectOptionsMap::const_iterator it = properties.find("hostName");
231+
232+
if (it != properties.end())
233+
{
234+
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
235+
236+
parseUri(*p_s, uri);
237+
} else {
238+
throw sql::InvalidArgumentException("No string value passed for hostName");
239+
}
240+
}
241+
242+
for (it = properties.begin(); it != properties.end(); ++it) {
243+
if (!it->first.compare("userName")) {
237244
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
238245
userName = *p_s;
239246
} else {
@@ -247,31 +254,28 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
247254
}
248255
} else if (!it->first.compare("port")) {
249256
if ((p_i = boost::get< int >(&it->second))) {
250-
port = static_cast<unsigned int>(*p_i);
257+
uri.setPort(static_cast<unsigned int>(*p_i));
251258
} else {
252259
throw sql::InvalidArgumentException("No long long value passed for port");
253260
}
254261
} else if (!it->first.compare("socket")) {
255262
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
256-
socket_or_pipe = *p_s;
263+
uri.setSocket(*p_s);
257264
} else {
258265
throw sql::InvalidArgumentException("No string value passed for socket");
259266
}
260-
protocol_tcp = false;
261267
} else if (!it->first.compare("pipe")) {
262268
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
263-
socket_or_pipe = *p_s;
269+
uri.setPipe(*p_s);
264270
} else {
265271
throw sql::InvalidArgumentException("No string value passed for pipe");
266272
}
267-
protocol_tcp = false;
268273
} else if (!it->first.compare("schema")) {
269274
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
270-
schema = *p_s;
275+
uri.setSchema(*p_s);
271276
} else {
272277
throw sql::InvalidArgumentException("No string value passed for schema");
273278
}
274-
schema_used = true;
275279
} else if (!it->first.compare("characterSetResults")) {
276280
if ((p_s = boost::get< sql::SQLString >(&it->second))) {
277281
characterSetResults = *p_s;
@@ -420,46 +424,10 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
420424
}
421425
}
422426

423-
#ifndef _WIN32
424-
if (!hostName.compare(0, sizeof("unix://") - 1, "unix://")) {
425-
protocol_tcp = false;
426-
socket_or_pipe = hostName.substr(sizeof("unix://") - 1, sql::SQLString::npos);
427-
host = "localhost";
428-
int tmp_protocol = MYSQL_PROTOCOL_SOCKET;
429-
proxy->options(MYSQL_OPT_PROTOCOL, (const char *) &tmp_protocol);
430-
} else
431-
#else
432-
if (!hostName.compare(0, sizeof("pipe://") - 1, "pipe://")) {
433-
protocol_tcp = false;
434-
socket_or_pipe = hostName.substr(sizeof("pipe://") - 1, sql::SQLString::npos);
435-
host = ".";
436-
int tmp_protocol = MYSQL_PROTOCOL_PIPE;
437-
proxy->options(MYSQL_OPT_PROTOCOL, (const char *) &tmp_protocol);
438-
} else
439-
#endif
440-
if (!hostName.compare(0, sizeof("tcp://") - 1, "tcp://") ) {
441-
size_t port_pos, schema_pos;
442-
host = hostName.substr(sizeof("tcp://") - 1, sql::SQLString::npos);
443-
schema_pos = host.find('/');
444-
if (schema_pos != sql::SQLString::npos) {
445-
++schema_pos; // skip the slash
446-
/* TODO: tcp://127.0.0.1/
447-
-> host set, schema empty, schema property ignored */
448-
schema = host.substr(schema_pos, host.length() - schema_pos);
449-
schema_used = true;
450-
host = host.substr(0, schema_pos - 1);
451-
}
452-
port_pos = host.find_last_of(':', sql::SQLString::npos);
453-
if (port_pos != sql::SQLString::npos) {
454-
port = atoi(host.substr(port_pos + 1, sql::SQLString::npos).c_str());
455-
host = host.substr(0, port_pos);
456-
}
457-
} else {
458-
host = hostName.c_str();
459-
}
427+
460428
/* libmysql shouldn't think it is too smart */
461-
if (protocol_tcp && !host.compare(0, sizeof("localhost") - 1, "localhost")) {
462-
host = "127.0.0.1";
429+
if (tcpProtocol(uri) && !uri.Host().compare(util::LOCALHOST)) {
430+
uri.setHost("127.0.0.1");
463431
}
464432

465433
it = properties.begin();
@@ -498,13 +466,24 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
498466
throw sql::InvalidArgumentException("No bool value passed for OPT_REPORT_DATA_TRUNCATION");
499467
}
500468
proxy->options(MYSQL_REPORT_DATA_TRUNCATION, (const char *) p_b);
501-
#ifdef _WIN32
502469
} else if (!it->first.compare("OPT_NAMED_PIPE")) {
503-
proxy->options(MYSQL_OPT_NAMED_PIPE, NULL);
504-
#endif
470+
/* Not sure it is really needed */
471+
uri.setProtocol(NativeAPI::PROTOCOL_PIPE);
505472
}
506473
}
507474

475+
// Throwing in case of wrong protocol
476+
#ifdef _WIN32
477+
if (uri.Protocol() == NativeAPI::PROTOCOL_SOCKET) {
478+
throw sql::InvalidArgumentException("Invalid for this platform protocol requested(MYSQL_PROTOCOL_SOCKET)");
479+
}
480+
#else
481+
if (uri.Protocol() == NativeAPI::PROTOCOL_PIPE) {
482+
throw sql::InvalidArgumentException("Invalid for this platform protocol requested(MYSQL_PROTOCOL_PIPE)");
483+
}
484+
#endif
485+
proxy->use_protocol(uri.Protocol());
486+
508487
{
509488
my_bool tmp_bool = 1;
510489
proxy->options(MYSQL_SECURE_AUTH, (const char *) &tmp_bool);
@@ -516,17 +495,17 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
516495
/* According to the docs, always returns 0 */
517496
proxy->ssl_set(sslKey.c_str(), sslCert.c_str(), sslCA.c_str(), sslCAPath.c_str(), sslCipher.c_str());
518497
}
519-
CPP_INFO_FMT("hostName=%s", hostName.c_str());
498+
CPP_INFO_FMT("hostName=%s", uri.Host().c_str());
520499
CPP_INFO_FMT("user=%s", userName.c_str());
521-
CPP_INFO_FMT("port=%d", port);
522-
CPP_INFO_FMT("schema=%s", schema.c_str());
523-
CPP_INFO_FMT("socket/pipe=%s", socket_or_pipe.c_str());
524-
if (!proxy->connect(host,
500+
CPP_INFO_FMT("port=%d", uri.Port());
501+
CPP_INFO_FMT("schema=%s", uri.Schema().c_str());
502+
CPP_INFO_FMT("socket/pipe=%s", uri.SocketOrPipe().c_str());
503+
if (!proxy->connect(uri.Host(),
525504
userName,
526505
password,
527-
schema_used && schema.length()? schema: (schema= "") /* schema */,
528-
port,
529-
protocol_tcp == false? socket_or_pipe : "" /*socket or named pipe */,
506+
uri.Schema() /* schema */,
507+
uri.Port(),
508+
uri.SocketOrPipe() /*socket or named pipe */,
530509
flags))
531510
{
532511
CPP_ERR_FMT("Couldn't connect : %d", proxy->errNo());

driver/mysql_connection_data.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3434
#include "mysql_util.h"
3535
#include "mysql_metadata.h"
3636
#include "mysql_warning.h"
37-
struct st_mysql;
3837

3938
namespace sql
4039
{

0 commit comments

Comments
 (0)