Skip to content

Commit 68a7967

Browse files
committed
SF [2643953] Improve Data::Session connection
1 parent 9bef44c commit 68a7967

50 files changed

Lines changed: 679 additions & 155 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Data/MySQL/include/Poco/Data/MySQL/Connector.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ class MySQL_API Connector: public Poco::Data::Connector
6262
virtual const std::string& name() const;
6363
/// Returns the name associated with this connector.
6464

65-
virtual Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
65+
virtual Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
66+
std::size_t timeout = Poco::Data::SessionImpl::CONNECT_TIMEOUT_DEFAULT);
6667
/// Creates a MySQL SessionImpl object and initializes it with the given connectionString.
6768

6869
static void registerConnector();

Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,18 @@ class SessionHandle
5959
~SessionHandle();
6060
/// Destroy handle, close connection
6161

62+
void init(MYSQL* mysql = 0);
63+
/// Initializes the handle iff not initialized.
64+
6265
void options(mysql_option opt);
6366
/// Set connection options
6467

6568
void options(mysql_option opt, bool b);
6669
/// Set connection options
6770

71+
void options(mysql_option opt, unsigned int i);
72+
/// Set connection options
73+
6874
void connect(const char* host, const char* user, const char* password, const char* db, unsigned int port);
6975
/// Connect to server
7076

Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ class MySQL_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
6262
static const std::string MYSQL_REPEATABLE_READ;
6363
static const std::string MYSQL_SERIALIZABLE;
6464

65-
SessionImpl(const std::string& connectionString);
65+
SessionImpl(const std::string& connectionString,
66+
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT);
6667
/// Creates the SessionImpl. Opens a connection to the database
6768
///
6869
/// Connection string format:
@@ -81,6 +82,15 @@ class MySQL_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
8182
Poco::Data::StatementImpl* createStatementImpl();
8283
/// Returns an MySQL StatementImpl
8384

85+
void open(const std::string& connection = "");
86+
/// Opens a connection to the database.
87+
88+
void close();
89+
/// Closes the connection.
90+
91+
bool isConnected();
92+
/// Returns true if connected, false otherwise.
93+
8494
void begin();
8595
/// Starts a transaction
8696

@@ -90,12 +100,6 @@ class MySQL_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
90100
void rollback();
91101
/// Aborts a transaction
92102

93-
void close();
94-
/// Closes the connection
95-
96-
bool isConnected();
97-
/// Returns true if connected, false otherwise.
98-
99103
bool canTransact();
100104
/// Returns true if session has transaction capabilities.
101105

@@ -163,10 +167,10 @@ class MySQL_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
163167
return getValue<T>(pResult, val);
164168
}
165169

166-
std::string _connector;
167-
SessionHandle _handle;
168-
bool _connected;
169-
bool _inTransaction;
170+
std::string _connector;
171+
SessionHandle _handle;
172+
bool _connected;
173+
bool _inTransaction;
170174
Poco::FastMutex _mutex;
171175
};
172176

Data/MySQL/src/Connector.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ const std::string& Connector::name() const
6464
return KEY;
6565
}
6666

67-
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString)
67+
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
68+
std::size_t timeout)
6869
{
69-
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString));
70+
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
7071
}
7172

7273

Data/MySQL/src/SessionHandle.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,28 @@
3535

3636

3737
#include "Poco/Data/MySQL/SessionHandle.h"
38+
#include "Poco/Data/DataException.h"
3839

3940

4041
namespace Poco {
4142
namespace Data {
4243
namespace MySQL {
4344

4445

45-
SessionHandle::SessionHandle(MYSQL* mysql)
46+
SessionHandle::SessionHandle(MYSQL* mysql): _pHandle(0)
4647
{
47-
if (!(_pHandle = mysql_init(mysql)))
48-
throw ConnectionException("mysql_init error");
48+
init(mysql);
49+
}
50+
51+
52+
void SessionHandle::init(MYSQL* mysql)
53+
{
54+
if (!_pHandle)
55+
{
56+
_pHandle = mysql_init(mysql);
57+
if (!_pHandle)
58+
throw ConnectionException("mysql_init error");
59+
}
4960
}
5061

5162

@@ -69,11 +80,17 @@ void SessionHandle::options(mysql_option opt, bool b)
6980
throw ConnectionException("mysql_options error", _pHandle);
7081
}
7182

83+
void SessionHandle::options(mysql_option opt, unsigned int i)
84+
{
85+
if (mysql_options(_pHandle, opt, &i) != 0)
86+
throw ConnectionException("mysql_options error", _pHandle);
87+
}
88+
7289

7390
void SessionHandle::connect(const char* host, const char* user, const char* password, const char* db, unsigned int port)
7491
{
7592
if (!mysql_real_connect(_pHandle, host, user, password, db, port, 0, 0))
76-
throw ConnectionException("create session: mysql_real_connect error", _pHandle);
93+
throw ConnectionFailedException("mysql_real_connect error");
7794
}
7895

7996

Data/MySQL/src/SessionImpl.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ const std::string SessionImpl::MYSQL_REPEATABLE_READ = "REPEATABLE READ";
6666
const std::string SessionImpl::MYSQL_SERIALIZABLE = "SERIALIZABLE";
6767

6868

69-
SessionImpl::SessionImpl(const std::string& connectionString) :
70-
Poco::Data::AbstractSessionImpl<SessionImpl>(toLower(connectionString)),
69+
SessionImpl::SessionImpl(const std::string& connectionString, std::size_t timeout) :
70+
Poco::Data::AbstractSessionImpl<SessionImpl>(toLower(connectionString), timeout),
7171
_handle(0),
7272
_connected(false),
7373
_inTransaction(false)
@@ -76,6 +76,28 @@ SessionImpl::SessionImpl(const std::string& connectionString) :
7676
&SessionImpl::setInsertId,
7777
&SessionImpl::getInsertId);
7878

79+
open();
80+
}
81+
82+
83+
void SessionImpl::open(const std::string& connect)
84+
{
85+
if (connect != connectionString())
86+
{
87+
if (isConnected())
88+
throw InvalidAccessException("Session already connected");
89+
90+
if (!connect.empty())
91+
setConnectionString(connect);
92+
}
93+
94+
poco_assert_dbg (!connectionString().empty());
95+
96+
_handle.init();
97+
98+
unsigned int timeout = static_cast<unsigned int>(getTimeout());
99+
_handle.options(MYSQL_OPT_CONNECT_TIMEOUT, timeout);
100+
79101
std::map<std::string, std::string> options;
80102

81103
// Default values
@@ -87,17 +109,18 @@ SessionImpl::SessionImpl(const std::string& connectionString) :
87109
options["compress"] = "";
88110
options["auto-reconnect"] = "";
89111

90-
for (std::string::const_iterator start = connectionString.begin();;)
112+
const std::string& connString = connectionString();
113+
for (std::string::const_iterator start = connString.begin();;)
91114
{
92-
std::string::const_iterator finish = std::find(start, connectionString.end(), ';');
115+
std::string::const_iterator finish = std::find(start, connString.end(), ';');
93116
std::string::const_iterator middle = std::find(start, finish, '=');
94117

95118
if (middle == finish)
96119
throw MySQLException("create session: bad connection string format, can not find '='");
97120

98121
options[copyStripped(start, middle)] = copyStripped(middle + 1, finish);
99122

100-
if ((finish == connectionString.end()) || (finish + 1 == connectionString.end())) break;
123+
if ((finish == connString.end()) || (finish + 1 == connString.end())) break;
101124

102125
start = finish + 1;
103126
}
@@ -127,8 +150,7 @@ SessionImpl::SessionImpl(const std::string& connectionString) :
127150
throw MySQLException("create session: specify correct auto-reconnect option (true or false) or skip it");
128151

129152
// Real connect
130-
_handle.connect(
131-
options["host"].c_str(),
153+
_handle.connect(options["host"].c_str(),
132154
options["user"].c_str(),
133155
options["password"].c_str(),
134156
options["db"].c_str(),

Data/MySQL/testsuite/src/MySQLTest.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,15 @@ void MySQLTest::testTransaction()
507507
}
508508

509509

510+
void MySQLTest::testReconnect()
511+
{
512+
if (!_pSession) fail ("Test not available.");
513+
514+
recreatePersonTable();
515+
_pExecutor->reconnect();
516+
}
517+
518+
510519
void MySQLTest::testNullableInt()
511520
{
512521
if (!_pSession) fail ("Test not available.");
@@ -813,6 +822,7 @@ CppUnit::Test* MySQLTest::suite()
813822
CppUnit_addTest(pSuite, MySQLTest, testTupleWithNullable);
814823
CppUnit_addTest(pSuite, MySQLTest, testSessionTransaction);
815824
CppUnit_addTest(pSuite, MySQLTest, testTransaction);
825+
CppUnit_addTest(pSuite, MySQLTest, testReconnect);
816826

817827
return pSuite;
818828
}

Data/MySQL/testsuite/src/MySQLTest.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ class MySQLTest: public CppUnit::TestCase
116116
void testSessionTransaction();
117117
void testTransaction();
118118

119+
void testReconnect();
120+
119121
void setUp();
120122
void tearDown();
121123

Data/MySQL/testsuite/src/SQLExecutor.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ void SQLExecutor::insertSingleBulk()
476476

477477
for (x = 0; x < 100; ++x)
478478
{
479-
int i = stmt.execute();
479+
std::size_t i = stmt.execute();
480480
assert (i == 0);
481481
}
482482

@@ -1803,3 +1803,44 @@ void SQLExecutor::transaction(const std::string& connect)
18031803

18041804
_pSession->setFeature("autoCommit", autoCommit);
18051805
}
1806+
1807+
1808+
void SQLExecutor::reconnect()
1809+
{
1810+
std::string funct = "reconnect()";
1811+
std::string lastName = "lastName";
1812+
std::string firstName("firstName");
1813+
std::string address("Address");
1814+
int age = 133132;
1815+
int count = 0;
1816+
std::string result;
1817+
1818+
try { (*_pSession) << "INSERT INTO PERSON VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; }
1819+
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
1820+
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
1821+
1822+
count = 0;
1823+
try { (*_pSession) << "SELECT COUNT(*) FROM PERSON", into(count), now; }
1824+
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
1825+
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
1826+
assert (count == 1);
1827+
1828+
assert (_pSession->isConnected());
1829+
_pSession->close();
1830+
assert (!_pSession->isConnected());
1831+
try
1832+
{
1833+
(*_pSession) << "SELECT LastName FROM PERSON", into(result), now;
1834+
fail ("must fail");
1835+
}
1836+
catch(NotConnectedException&){ }
1837+
assert (!_pSession->isConnected());
1838+
1839+
_pSession->open();
1840+
assert (_pSession->isConnected());
1841+
try { (*_pSession) << "SELECT Age FROM PERSON", into(count), now; }
1842+
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
1843+
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
1844+
assert (count == age);
1845+
assert (_pSession->isConnected());
1846+
}

Data/MySQL/testsuite/src/SQLExecutor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ class SQLExecutor: public CppUnit::TestCase
113113
void sessionTransaction(const std::string& connect);
114114
void transaction(const std::string& connect);
115115

116+
void reconnect();
117+
116118
private:
117119
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
118120

0 commit comments

Comments
 (0)