Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed MySQL session reset #2801

Open
wants to merge 3 commits into
base: poco-1.10.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions Data/MySQL/src/SessionHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,21 @@ void SessionHandle::rollback()

void SessionHandle::reset()
{
#if ((defined (MYSQL_VERSION_ID)) && (MYSQL_VERSION_ID >= 50700)) || ((defined (MARIADB_PACKAGE_VERSION_ID)) && (MARIADB_PACKAGE_VERSION_ID >= 30000))
if (mysql_reset_connection(_pHandle) != 0)
#else
if (mysql_refresh(_pHandle, REFRESH_TABLES | REFRESH_STATUS | REFRESH_THREADS | REFRESH_READ_LOCK) != 0)
#endif
/*
We have to somehow reset sessions before getting session from session pool, because sometimes
used session has some remains from previous usage.

First, we tried call mysql_refresh() (now obsolete) and then mysql_reset_connection(). Both of
these functions caused unintended reseting of variables holding charset/encoding (internal variables
like "session.collation_connection" etc., was reseted to default value which is "latin1_swedish_ci").

Executing query FLUSH seems that it resets session and does not harm encoding.
I have tried few flush options (PRIVILEGES, USER_RESOURCES, QUERY CACHE, STATUS) and every of
these worked. Only option which did not work was FLUSH TABLES - it caused deadlocks. So I decided
call only FLUSH STATUS.
*/

if (mysql_query(_pHandle, "FLUSH STATUS;") != 0)
throw TransactionException("Reset connection failed.", _pHandle);
}

Expand Down
11 changes: 11 additions & 0 deletions Data/MySQL/testsuite/src/MySQLTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "Poco/Data/MySQL/MySQLException.h"
#include "Poco/Nullable.h"
#include "Poco/Data/DataException.h"
#include "Poco/Data/SessionPool.h"
#include <iostream>

using namespace Poco::Data;
Expand Down Expand Up @@ -423,6 +424,15 @@ void MySQLTest::testDateTime()
}


void MySQLTest::testSessionPoolAndUnicode()
{
if (!_pSession) fail ("Test not available.");

recreateStringsTable();
_pExecutor->sessionPoolAndUnicode(_dbConnString);
}


void MySQLTest::testBLOB()
{
if (!_pSession) fail ("Test not available.");
Expand Down Expand Up @@ -897,6 +907,7 @@ CppUnit::Test* MySQLTest::suite()
CppUnit_addTest(pSuite, MySQLTest, testSingleSelect);
CppUnit_addTest(pSuite, MySQLTest, testEmptyDB);
CppUnit_addTest(pSuite, MySQLTest, testDateTime);
CppUnit_addTest(pSuite, MySQLTest, testSessionPoolAndUnicode);
//CppUnit_addTest(pSuite, MySQLTest, testBLOB);
CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt);
CppUnit_addTest(pSuite, MySQLTest, testUnsignedInts);
Expand Down
1 change: 1 addition & 0 deletions Data/MySQL/testsuite/src/MySQLTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class MySQLTest: public CppUnit::TestCase
void testSingleSelect();
void testEmptyDB();
void testDateTime();
void testSessionPoolAndUnicode();
void testBLOB();
void testBLOBStmt();

Expand Down
29 changes: 29 additions & 0 deletions Data/MySQL/testsuite/src/SQLExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "Poco/Data/Transaction.h"
#include "Poco/Data/MySQL/Connector.h"
#include "Poco/Data/MySQL/MySQLException.h"
#include "Poco/Data/SessionPool.h"

#ifdef _WIN32
#include <Winsock2.h>
Expand Down Expand Up @@ -1462,6 +1463,34 @@ void SQLExecutor::tupleVector()
}


void SQLExecutor::sessionPoolAndUnicode(const std::string& connString)
{
std::string funct = "unicode()";
std::string text = "ěščřžťďůň";
std::string text2;

// Test uses session from SessionPool instead of _pSession to prove session
// obtained and returned into pool is valid.

// Min/Max 1 session - ensures that when get() is called, same session should be returned
Poco::SharedPtr<Poco::Data::SessionPool> sp = new Poco::Data::SessionPool(MySQL::Connector::KEY, connString, 1, 1);

{
Poco::Data::Session session = sp->get();
try { session << "INSERT INTO Strings VALUES (?)", use(text), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
} // parentheses to ensure session is returned into pool

Poco::Data::Session session2 = sp->get();
try { session2 << "SELECT str FROM Strings", into(text2), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }

assertTrue (text == text2);
}


void SQLExecutor::internalExtraction()
{
/*std::string funct = "internalExtraction()";
Expand Down
2 changes: 2 additions & 0 deletions Data/MySQL/testsuite/src/SQLExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ class SQLExecutor: public CppUnit::TestCase
void tuples();
void tupleVector();

void sessionPoolAndUnicode(const std::string& connString);

void internalExtraction();
void doNull();

Expand Down