mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-16 18:56:52 +02:00
SF [2643953] Improve Data::Session connection
This commit is contained in:
@@ -62,7 +62,8 @@ public:
|
|||||||
virtual const std::string& name() const;
|
virtual const std::string& name() const;
|
||||||
/// Returns the name associated with this connector.
|
/// Returns the name associated with this connector.
|
||||||
|
|
||||||
virtual Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
|
virtual Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout = Poco::Data::SessionImpl::CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a MySQL SessionImpl object and initializes it with the given connectionString.
|
/// Creates a MySQL SessionImpl object and initializes it with the given connectionString.
|
||||||
|
|
||||||
static void registerConnector();
|
static void registerConnector();
|
||||||
|
@@ -59,12 +59,18 @@ public:
|
|||||||
~SessionHandle();
|
~SessionHandle();
|
||||||
/// Destroy handle, close connection
|
/// Destroy handle, close connection
|
||||||
|
|
||||||
|
void init(MYSQL* mysql = 0);
|
||||||
|
/// Initializes the handle iff not initialized.
|
||||||
|
|
||||||
void options(mysql_option opt);
|
void options(mysql_option opt);
|
||||||
/// Set connection options
|
/// Set connection options
|
||||||
|
|
||||||
void options(mysql_option opt, bool b);
|
void options(mysql_option opt, bool b);
|
||||||
/// Set connection options
|
/// Set connection options
|
||||||
|
|
||||||
|
void options(mysql_option opt, unsigned int i);
|
||||||
|
/// Set connection options
|
||||||
|
|
||||||
void connect(const char* host, const char* user, const char* password, const char* db, unsigned int port);
|
void connect(const char* host, const char* user, const char* password, const char* db, unsigned int port);
|
||||||
/// Connect to server
|
/// Connect to server
|
||||||
|
|
||||||
|
@@ -62,7 +62,8 @@ public:
|
|||||||
static const std::string MYSQL_REPEATABLE_READ;
|
static const std::string MYSQL_REPEATABLE_READ;
|
||||||
static const std::string MYSQL_SERIALIZABLE;
|
static const std::string MYSQL_SERIALIZABLE;
|
||||||
|
|
||||||
SessionImpl(const std::string& connectionString);
|
SessionImpl(const std::string& connectionString,
|
||||||
|
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates the SessionImpl. Opens a connection to the database
|
/// Creates the SessionImpl. Opens a connection to the database
|
||||||
///
|
///
|
||||||
/// Connection string format:
|
/// Connection string format:
|
||||||
@@ -81,6 +82,15 @@ public:
|
|||||||
Poco::Data::StatementImpl* createStatementImpl();
|
Poco::Data::StatementImpl* createStatementImpl();
|
||||||
/// Returns an MySQL StatementImpl
|
/// Returns an MySQL StatementImpl
|
||||||
|
|
||||||
|
void open(const std::string& connection = "");
|
||||||
|
/// Opens a connection to the database.
|
||||||
|
|
||||||
|
void close();
|
||||||
|
/// Closes the connection.
|
||||||
|
|
||||||
|
bool isConnected();
|
||||||
|
/// Returns true if connected, false otherwise.
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
/// Starts a transaction
|
/// Starts a transaction
|
||||||
|
|
||||||
@@ -90,12 +100,6 @@ public:
|
|||||||
void rollback();
|
void rollback();
|
||||||
/// Aborts a transaction
|
/// Aborts a transaction
|
||||||
|
|
||||||
void close();
|
|
||||||
/// Closes the connection
|
|
||||||
|
|
||||||
bool isConnected();
|
|
||||||
/// Returns true if connected, false otherwise.
|
|
||||||
|
|
||||||
bool canTransact();
|
bool canTransact();
|
||||||
/// Returns true if session has transaction capabilities.
|
/// Returns true if session has transaction capabilities.
|
||||||
|
|
||||||
|
@@ -64,9 +64,10 @@ const std::string& Connector::name() const
|
|||||||
return KEY;
|
return KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString)
|
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString));
|
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/Data/MySQL/SessionHandle.h"
|
#include "Poco/Data/MySQL/SessionHandle.h"
|
||||||
|
#include "Poco/Data/DataException.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -42,10 +43,20 @@ namespace Data {
|
|||||||
namespace MySQL {
|
namespace MySQL {
|
||||||
|
|
||||||
|
|
||||||
SessionHandle::SessionHandle(MYSQL* mysql)
|
SessionHandle::SessionHandle(MYSQL* mysql): _pHandle(0)
|
||||||
{
|
{
|
||||||
if (!(_pHandle = mysql_init(mysql)))
|
init(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SessionHandle::init(MYSQL* mysql)
|
||||||
|
{
|
||||||
|
if (!_pHandle)
|
||||||
|
{
|
||||||
|
_pHandle = mysql_init(mysql);
|
||||||
|
if (!_pHandle)
|
||||||
throw ConnectionException("mysql_init error");
|
throw ConnectionException("mysql_init error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,11 +80,17 @@ void SessionHandle::options(mysql_option opt, bool b)
|
|||||||
throw ConnectionException("mysql_options error", _pHandle);
|
throw ConnectionException("mysql_options error", _pHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionHandle::options(mysql_option opt, unsigned int i)
|
||||||
|
{
|
||||||
|
if (mysql_options(_pHandle, opt, &i) != 0)
|
||||||
|
throw ConnectionException("mysql_options error", _pHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SessionHandle::connect(const char* host, const char* user, const char* password, const char* db, unsigned int port)
|
void SessionHandle::connect(const char* host, const char* user, const char* password, const char* db, unsigned int port)
|
||||||
{
|
{
|
||||||
if (!mysql_real_connect(_pHandle, host, user, password, db, port, 0, 0))
|
if (!mysql_real_connect(_pHandle, host, user, password, db, port, 0, 0))
|
||||||
throw ConnectionException("create session: mysql_real_connect error", _pHandle);
|
throw ConnectionFailedException("mysql_real_connect error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -66,8 +66,8 @@ const std::string SessionImpl::MYSQL_REPEATABLE_READ = "REPEATABLE READ";
|
|||||||
const std::string SessionImpl::MYSQL_SERIALIZABLE = "SERIALIZABLE";
|
const std::string SessionImpl::MYSQL_SERIALIZABLE = "SERIALIZABLE";
|
||||||
|
|
||||||
|
|
||||||
SessionImpl::SessionImpl(const std::string& connectionString) :
|
SessionImpl::SessionImpl(const std::string& connectionString, std::size_t timeout) :
|
||||||
Poco::Data::AbstractSessionImpl<SessionImpl>(toLower(connectionString)),
|
Poco::Data::AbstractSessionImpl<SessionImpl>(toLower(connectionString), timeout),
|
||||||
_handle(0),
|
_handle(0),
|
||||||
_connected(false),
|
_connected(false),
|
||||||
_inTransaction(false)
|
_inTransaction(false)
|
||||||
@@ -76,6 +76,28 @@ SessionImpl::SessionImpl(const std::string& connectionString) :
|
|||||||
&SessionImpl::setInsertId,
|
&SessionImpl::setInsertId,
|
||||||
&SessionImpl::getInsertId);
|
&SessionImpl::getInsertId);
|
||||||
|
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SessionImpl::open(const std::string& connect)
|
||||||
|
{
|
||||||
|
if (connect != connectionString())
|
||||||
|
{
|
||||||
|
if (isConnected())
|
||||||
|
throw InvalidAccessException("Session already connected");
|
||||||
|
|
||||||
|
if (!connect.empty())
|
||||||
|
setConnectionString(connect);
|
||||||
|
}
|
||||||
|
|
||||||
|
poco_assert_dbg (!connectionString().empty());
|
||||||
|
|
||||||
|
_handle.init();
|
||||||
|
|
||||||
|
unsigned int timeout = static_cast<unsigned int>(getTimeout());
|
||||||
|
_handle.options(MYSQL_OPT_CONNECT_TIMEOUT, timeout);
|
||||||
|
|
||||||
std::map<std::string, std::string> options;
|
std::map<std::string, std::string> options;
|
||||||
|
|
||||||
// Default values
|
// Default values
|
||||||
@@ -87,9 +109,10 @@ SessionImpl::SessionImpl(const std::string& connectionString) :
|
|||||||
options["compress"] = "";
|
options["compress"] = "";
|
||||||
options["auto-reconnect"] = "";
|
options["auto-reconnect"] = "";
|
||||||
|
|
||||||
for (std::string::const_iterator start = connectionString.begin();;)
|
const std::string& connString = connectionString();
|
||||||
|
for (std::string::const_iterator start = connString.begin();;)
|
||||||
{
|
{
|
||||||
std::string::const_iterator finish = std::find(start, connectionString.end(), ';');
|
std::string::const_iterator finish = std::find(start, connString.end(), ';');
|
||||||
std::string::const_iterator middle = std::find(start, finish, '=');
|
std::string::const_iterator middle = std::find(start, finish, '=');
|
||||||
|
|
||||||
if (middle == finish)
|
if (middle == finish)
|
||||||
@@ -97,7 +120,7 @@ SessionImpl::SessionImpl(const std::string& connectionString) :
|
|||||||
|
|
||||||
options[copyStripped(start, middle)] = copyStripped(middle + 1, finish);
|
options[copyStripped(start, middle)] = copyStripped(middle + 1, finish);
|
||||||
|
|
||||||
if ((finish == connectionString.end()) || (finish + 1 == connectionString.end())) break;
|
if ((finish == connString.end()) || (finish + 1 == connString.end())) break;
|
||||||
|
|
||||||
start = finish + 1;
|
start = finish + 1;
|
||||||
}
|
}
|
||||||
@@ -127,8 +150,7 @@ SessionImpl::SessionImpl(const std::string& connectionString) :
|
|||||||
throw MySQLException("create session: specify correct auto-reconnect option (true or false) or skip it");
|
throw MySQLException("create session: specify correct auto-reconnect option (true or false) or skip it");
|
||||||
|
|
||||||
// Real connect
|
// Real connect
|
||||||
_handle.connect(
|
_handle.connect(options["host"].c_str(),
|
||||||
options["host"].c_str(),
|
|
||||||
options["user"].c_str(),
|
options["user"].c_str(),
|
||||||
options["password"].c_str(),
|
options["password"].c_str(),
|
||||||
options["db"].c_str(),
|
options["db"].c_str(),
|
||||||
|
@@ -507,6 +507,15 @@ void MySQLTest::testTransaction()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MySQLTest::testReconnect()
|
||||||
|
{
|
||||||
|
if (!_pSession) fail ("Test not available.");
|
||||||
|
|
||||||
|
recreatePersonTable();
|
||||||
|
_pExecutor->reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MySQLTest::testNullableInt()
|
void MySQLTest::testNullableInt()
|
||||||
{
|
{
|
||||||
if (!_pSession) fail ("Test not available.");
|
if (!_pSession) fail ("Test not available.");
|
||||||
@@ -813,6 +822,7 @@ CppUnit::Test* MySQLTest::suite()
|
|||||||
CppUnit_addTest(pSuite, MySQLTest, testTupleWithNullable);
|
CppUnit_addTest(pSuite, MySQLTest, testTupleWithNullable);
|
||||||
CppUnit_addTest(pSuite, MySQLTest, testSessionTransaction);
|
CppUnit_addTest(pSuite, MySQLTest, testSessionTransaction);
|
||||||
CppUnit_addTest(pSuite, MySQLTest, testTransaction);
|
CppUnit_addTest(pSuite, MySQLTest, testTransaction);
|
||||||
|
CppUnit_addTest(pSuite, MySQLTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -116,6 +116,8 @@ public:
|
|||||||
void testSessionTransaction();
|
void testSessionTransaction();
|
||||||
void testTransaction();
|
void testTransaction();
|
||||||
|
|
||||||
|
void testReconnect();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
|
||||||
|
@@ -476,7 +476,7 @@ void SQLExecutor::insertSingleBulk()
|
|||||||
|
|
||||||
for (x = 0; x < 100; ++x)
|
for (x = 0; x < 100; ++x)
|
||||||
{
|
{
|
||||||
int i = stmt.execute();
|
std::size_t i = stmt.execute();
|
||||||
assert (i == 0);
|
assert (i == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1803,3 +1803,44 @@ void SQLExecutor::transaction(const std::string& connect)
|
|||||||
|
|
||||||
_pSession->setFeature("autoCommit", autoCommit);
|
_pSession->setFeature("autoCommit", autoCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLExecutor::reconnect()
|
||||||
|
{
|
||||||
|
std::string funct = "reconnect()";
|
||||||
|
std::string lastName = "lastName";
|
||||||
|
std::string firstName("firstName");
|
||||||
|
std::string address("Address");
|
||||||
|
int age = 133132;
|
||||||
|
int count = 0;
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
try { (*_pSession) << "INSERT INTO PERSON VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
try { (*_pSession) << "SELECT COUNT(*) FROM PERSON", into(count), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||||
|
assert (count == 1);
|
||||||
|
|
||||||
|
assert (_pSession->isConnected());
|
||||||
|
_pSession->close();
|
||||||
|
assert (!_pSession->isConnected());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
(*_pSession) << "SELECT LastName FROM PERSON", into(result), now;
|
||||||
|
fail ("must fail");
|
||||||
|
}
|
||||||
|
catch(NotConnectedException&){ }
|
||||||
|
assert (!_pSession->isConnected());
|
||||||
|
|
||||||
|
_pSession->open();
|
||||||
|
assert (_pSession->isConnected());
|
||||||
|
try { (*_pSession) << "SELECT Age FROM PERSON", into(count), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||||
|
assert (count == age);
|
||||||
|
assert (_pSession->isConnected());
|
||||||
|
}
|
||||||
|
@@ -113,6 +113,8 @@ public:
|
|||||||
void sessionTransaction(const std::string& connect);
|
void sessionTransaction(const std::string& connect);
|
||||||
void transaction(const std::string& connect);
|
void transaction(const std::string& connect);
|
||||||
|
|
||||||
|
void reconnect();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
|
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
|
||||||
|
|
||||||
|
@@ -65,7 +65,8 @@ public:
|
|||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
/// Returns the name associated with this connector.
|
/// Returns the name associated with this connector.
|
||||||
|
|
||||||
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
|
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout = Poco::Data::SessionImpl::CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a ODBC SessionImpl object and initializes it with the given connectionString.
|
/// Creates a ODBC SessionImpl object and initializes it with the given connectionString.
|
||||||
|
|
||||||
static void registerConnector();
|
static void registerConnector();
|
||||||
|
@@ -64,6 +64,8 @@ class ODBC_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
|
|||||||
/// Implements SessionImpl interface
|
/// Implements SessionImpl interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u;
|
||||||
|
|
||||||
enum TransactionCapability
|
enum TransactionCapability
|
||||||
{
|
{
|
||||||
ODBC_TXN_CAPABILITY_UNKNOWN = -1,
|
ODBC_TXN_CAPABILITY_UNKNOWN = -1,
|
||||||
@@ -72,11 +74,20 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SessionImpl(const std::string& connect,
|
SessionImpl(const std::string& connect,
|
||||||
Poco::Any maxFieldSize = std::size_t(1024),
|
std::size_t timeout,
|
||||||
|
std::size_t maxFieldSize = ODBC_MAX_FIELD_SIZE,
|
||||||
|
bool autoBind = true,
|
||||||
|
bool autoExtract = true);
|
||||||
|
/// Creates the SessionImpl. Opens a connection to the database.
|
||||||
|
/// Throws NotConnectedException if connection was not succesful.
|
||||||
|
|
||||||
|
//@ deprecated
|
||||||
|
SessionImpl(const std::string& connect,
|
||||||
|
Poco::Any maxFieldSize = ODBC_MAX_FIELD_SIZE,
|
||||||
bool enforceCapability=false,
|
bool enforceCapability=false,
|
||||||
bool autoBind = true,
|
bool autoBind = true,
|
||||||
bool autoExtract = true);
|
bool autoExtract = true);
|
||||||
/// Creates the SessionImpl. Opens a connection to the database
|
/// Creates the SessionImpl. Opens a connection to the database.
|
||||||
|
|
||||||
~SessionImpl();
|
~SessionImpl();
|
||||||
/// Destroys the SessionImpl.
|
/// Destroys the SessionImpl.
|
||||||
@@ -84,6 +95,15 @@ public:
|
|||||||
Poco::Data::StatementImpl* createStatementImpl();
|
Poco::Data::StatementImpl* createStatementImpl();
|
||||||
/// Returns an ODBC StatementImpl
|
/// Returns an ODBC StatementImpl
|
||||||
|
|
||||||
|
void open(const std::string& connect = "");
|
||||||
|
/// Opens a connection to the Database
|
||||||
|
|
||||||
|
void close();
|
||||||
|
/// Closes the connection
|
||||||
|
|
||||||
|
bool isConnected();
|
||||||
|
/// Returns true if session is connected
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
/// Starts a transaction
|
/// Starts a transaction
|
||||||
|
|
||||||
@@ -93,12 +113,6 @@ public:
|
|||||||
void rollback();
|
void rollback();
|
||||||
/// Aborts a transaction
|
/// Aborts a transaction
|
||||||
|
|
||||||
void close();
|
|
||||||
/// Closes the connection
|
|
||||||
|
|
||||||
bool isConnected();
|
|
||||||
/// Returns true if session is connected
|
|
||||||
|
|
||||||
bool isTransaction();
|
bool isTransaction();
|
||||||
/// Returns true iff a transaction is in progress.
|
/// Returns true iff a transaction is in progress.
|
||||||
|
|
||||||
@@ -161,9 +175,6 @@ private:
|
|||||||
|
|
||||||
static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
|
static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
|
||||||
|
|
||||||
void open();
|
|
||||||
/// Opens a connection to the Database
|
|
||||||
|
|
||||||
void checkError(SQLRETURN rc, const std::string& msg="");
|
void checkError(SQLRETURN rc, const std::string& msg="");
|
||||||
|
|
||||||
Poco::UInt32 getDefaultTransactionIsolation();
|
Poco::UInt32 getDefaultTransactionIsolation();
|
||||||
|
@@ -57,9 +57,10 @@ Connector::~Connector()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString)
|
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString));
|
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -49,6 +49,24 @@ namespace Data {
|
|||||||
namespace ODBC {
|
namespace ODBC {
|
||||||
|
|
||||||
|
|
||||||
|
SessionImpl::SessionImpl(const std::string& connect,
|
||||||
|
std::size_t timeout,
|
||||||
|
std::size_t maxFieldSize,
|
||||||
|
bool autoBind,
|
||||||
|
bool autoExtract):
|
||||||
|
Poco::Data::AbstractSessionImpl<SessionImpl>(connect, timeout),
|
||||||
|
_connector(toLower(Connector::KEY)),
|
||||||
|
_maxFieldSize(maxFieldSize),
|
||||||
|
_autoBind(autoBind),
|
||||||
|
_autoExtract(autoExtract),
|
||||||
|
_canTransact(ODBC_TXN_CAPABILITY_UNKNOWN),
|
||||||
|
_inTransaction(false)
|
||||||
|
{
|
||||||
|
setFeature("bulk", true);
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SessionImpl::SessionImpl(const std::string& connect,
|
SessionImpl::SessionImpl(const std::string& connect,
|
||||||
Poco::Any maxFieldSize,
|
Poco::Any maxFieldSize,
|
||||||
bool enforceCapability,
|
bool enforceCapability,
|
||||||
@@ -85,8 +103,30 @@ Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SessionImpl::open()
|
void SessionImpl::open(const std::string& connect)
|
||||||
{
|
{
|
||||||
|
if (connect != connectionString())
|
||||||
|
{
|
||||||
|
if (isConnected())
|
||||||
|
throw InvalidAccessException("Session already connected");
|
||||||
|
|
||||||
|
if (!connect.empty())
|
||||||
|
setConnectionString(connect);
|
||||||
|
}
|
||||||
|
|
||||||
|
poco_assert_dbg (!connectionString().empty());
|
||||||
|
|
||||||
|
SQLUINTEGER tout = static_cast<SQLUINTEGER>(getTimeout());
|
||||||
|
if (Utility::isError(SQLSetConnectAttr(_db, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) tout, 0)))
|
||||||
|
{
|
||||||
|
if (Utility::isError(SQLGetConnectAttr(_db, SQL_ATTR_LOGIN_TIMEOUT, &tout, 0, 0)) ||
|
||||||
|
getTimeout() != tout)
|
||||||
|
{
|
||||||
|
ConnectionError e(_db);
|
||||||
|
throw ConnectionFailedException(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SQLCHAR connectOutput[512] = {0};
|
SQLCHAR connectOutput[512] = {0};
|
||||||
SQLSMALLINT result;
|
SQLSMALLINT result;
|
||||||
|
|
||||||
@@ -99,9 +139,10 @@ void SessionImpl::open()
|
|||||||
, &result
|
, &result
|
||||||
, SQL_DRIVER_NOPROMPT)))
|
, SQL_DRIVER_NOPROMPT)))
|
||||||
{
|
{
|
||||||
ConnectionException exc(_db);
|
ConnectionError err(_db);
|
||||||
|
std::string errStr = err.toString();
|
||||||
close();
|
close();
|
||||||
throw exc;
|
throw ConnectionFailedException(errStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dataTypes.fillTypeInfo(_db);
|
_dataTypes.fillTypeInfo(_db);
|
||||||
|
@@ -681,6 +681,7 @@ CppUnit::Test* ODBCDB2Test::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSessionTransaction);
|
CppUnit_addTest(pSuite, ODBCDB2Test, testSessionTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTransaction);
|
CppUnit_addTest(pSuite, ODBCDB2Test, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTransactor);
|
CppUnit_addTest(pSuite, ODBCDB2Test, testTransactor);
|
||||||
|
CppUnit_addTest(pSuite, ODBCDB2Test, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -497,6 +497,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSessionTransaction);
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testSessionTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testTransactor);
|
||||||
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -922,6 +922,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSessionTransaction);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testSessionTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testTransactor);
|
||||||
|
CppUnit_addTest(pSuite, ODBCOracleTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -659,6 +659,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSessionTransaction);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSessionTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTransactor);
|
||||||
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -809,6 +809,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSessionTransaction);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSessionTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactor);
|
||||||
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -400,6 +400,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSessionTransaction);
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSessionTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTransaction);
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTransaction);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTransactor);
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTransactor);
|
||||||
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -47,12 +47,14 @@
|
|||||||
#include "Poco/Data/ODBC/Diagnostics.h"
|
#include "Poco/Data/ODBC/Diagnostics.h"
|
||||||
#include "Poco/Data/ODBC/ODBCException.h"
|
#include "Poco/Data/ODBC/ODBCException.h"
|
||||||
#include "Poco/Data/ODBC/ODBCStatementImpl.h"
|
#include "Poco/Data/ODBC/ODBCStatementImpl.h"
|
||||||
|
#include "Poco/Data/DataException.h"
|
||||||
#include <sqltypes.h>
|
#include <sqltypes.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
using namespace Poco::Data::Keywords;
|
using namespace Poco::Data::Keywords;
|
||||||
using Poco::Data::Session;
|
using Poco::Data::Session;
|
||||||
|
using Poco::Data::ConnectionFailedException;
|
||||||
using Poco::Data::CLOB;
|
using Poco::Data::CLOB;
|
||||||
using Poco::Data::ODBC::Utility;
|
using Poco::Data::ODBC::Utility;
|
||||||
using Poco::Data::ODBC::ODBCException;
|
using Poco::Data::ODBC::ODBCException;
|
||||||
@@ -1187,6 +1189,23 @@ void ODBCTest::testTransactor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCTest::testReconnect()
|
||||||
|
{
|
||||||
|
if (!_pSession) fail ("Test not available.");
|
||||||
|
|
||||||
|
std::string tableName("Person");
|
||||||
|
|
||||||
|
for (int i = 0; i < 8;)
|
||||||
|
{
|
||||||
|
recreatePersonTable();
|
||||||
|
_pSession->setFeature("autoBind", bindValue(i));
|
||||||
|
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||||
|
_pExecutor->reconnect();
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ODBCTest::canConnect(const std::string& driver,
|
bool ODBCTest::canConnect(const std::string& driver,
|
||||||
std::string& dsn,
|
std::string& dsn,
|
||||||
std::string& uid,
|
std::string& uid,
|
||||||
@@ -1262,9 +1281,9 @@ ODBCTest::SessionPtr ODBCTest::init(const std::string& driver,
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new Session(Poco::Data::ODBC::Connector::KEY, dbConnString);
|
return new Session(Poco::Data::ODBC::Connector::KEY, dbConnString);
|
||||||
}catch (ConnectionException& ex)
|
}catch (ConnectionFailedException& ex)
|
||||||
{
|
{
|
||||||
std::cout << ex.toString() << std::endl;
|
std::cout << ex.displayText() << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -167,6 +167,8 @@ public:
|
|||||||
virtual void testTransaction();
|
virtual void testTransaction();
|
||||||
virtual void testTransactor();
|
virtual void testTransactor();
|
||||||
|
|
||||||
|
virtual void testReconnect();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef Poco::Data::ODBC::Utility::DriverMap Drivers;
|
typedef Poco::Data::ODBC::Utility::DriverMap Drivers;
|
||||||
|
|
||||||
|
@@ -85,6 +85,7 @@ using Poco::Data::CLOB;
|
|||||||
using Poco::Data::Date;
|
using Poco::Data::Date;
|
||||||
using Poco::Data::Time;
|
using Poco::Data::Time;
|
||||||
using Poco::Data::Transaction;
|
using Poco::Data::Transaction;
|
||||||
|
using Poco::Data::NotConnectedException;
|
||||||
using Poco::Data::ODBC::Utility;
|
using Poco::Data::ODBC::Utility;
|
||||||
using Poco::Data::ODBC::Preparator;
|
using Poco::Data::ODBC::Preparator;
|
||||||
using Poco::Data::ODBC::ConnectionException;
|
using Poco::Data::ODBC::ConnectionException;
|
||||||
@@ -3763,3 +3764,44 @@ void SQLExecutor::transactor()
|
|||||||
|
|
||||||
session().setFeature("autoCommit", autoCommit);
|
session().setFeature("autoCommit", autoCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLExecutor::reconnect()
|
||||||
|
{
|
||||||
|
std::string funct = "reconnect()";
|
||||||
|
std::string lastName = "lastName";
|
||||||
|
std::string firstName("firstName");
|
||||||
|
std::string address("Address");
|
||||||
|
int age = 133132;
|
||||||
|
int count = 0;
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
try { session() << "INSERT INTO PERSON VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
try { session() << "SELECT COUNT(*) FROM PERSON", into(count), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||||
|
assert (count == 1);
|
||||||
|
|
||||||
|
assert (session().isConnected());
|
||||||
|
session().close();
|
||||||
|
assert (!session().isConnected());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
session() << "SELECT LastName FROM PERSON", into(result), now;
|
||||||
|
fail ("must fail");
|
||||||
|
}
|
||||||
|
catch(NotConnectedException&){ }
|
||||||
|
assert (!session().isConnected());
|
||||||
|
|
||||||
|
session().open();
|
||||||
|
assert (session().isConnected());
|
||||||
|
try { session() << "SELECT Age FROM PERSON", into(count), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||||
|
assert (count == age);
|
||||||
|
assert (session().isConnected());
|
||||||
|
}
|
||||||
|
@@ -518,6 +518,8 @@ public:
|
|||||||
void transaction(const std::string& connect);
|
void transaction(const std::string& connect);
|
||||||
void transactor();
|
void transactor();
|
||||||
|
|
||||||
|
void reconnect();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const std::string MULTI_INSERT;
|
static const std::string MULTI_INSERT;
|
||||||
static const std::string MULTI_SELECT;
|
static const std::string MULTI_SELECT;
|
||||||
|
@@ -65,7 +65,8 @@ public:
|
|||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
/// Returns the name associated with this connector.
|
/// Returns the name associated with this connector.
|
||||||
|
|
||||||
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
|
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout = Poco::Data::SessionImpl::CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a SQLite SessionImpl object and initializes it with the given connectionString.
|
/// Creates a SQLite SessionImpl object and initializes it with the given connectionString.
|
||||||
|
|
||||||
static void registerConnector();
|
static void registerConnector();
|
||||||
|
@@ -59,7 +59,8 @@ class SQLite_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl
|
|||||||
/// Implements SessionImpl interface.
|
/// Implements SessionImpl interface.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SessionImpl(const std::string& fileName);
|
SessionImpl(const std::string& fileName,
|
||||||
|
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates the SessionImpl. Opens a connection to the database.
|
/// Creates the SessionImpl. Opens a connection to the database.
|
||||||
|
|
||||||
~SessionImpl();
|
~SessionImpl();
|
||||||
@@ -77,6 +78,9 @@ public:
|
|||||||
void rollback();
|
void rollback();
|
||||||
/// Aborts a transaction.
|
/// Aborts a transaction.
|
||||||
|
|
||||||
|
void open(const std::string& connect = "");
|
||||||
|
/// Opens a connection to the Database.
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
/// Closes the session.
|
/// Closes the session.
|
||||||
|
|
||||||
@@ -107,8 +111,6 @@ public:
|
|||||||
/// Returns the name of the connector.
|
/// Returns the name of the connector.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void open();
|
|
||||||
/// Opens a connection to the Database.
|
|
||||||
|
|
||||||
std::string _connector;
|
std::string _connector;
|
||||||
sqlite3* _pDB;
|
sqlite3* _pDB;
|
||||||
|
@@ -58,9 +58,10 @@ Connector::~Connector()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString)
|
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString));
|
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -38,7 +38,10 @@
|
|||||||
#include "Poco/Data/SQLite/Utility.h"
|
#include "Poco/Data/SQLite/Utility.h"
|
||||||
#include "Poco/Data/SQLite/SQLiteStatementImpl.h"
|
#include "Poco/Data/SQLite/SQLiteStatementImpl.h"
|
||||||
#include "Poco/Data/SQLite/Connector.h"
|
#include "Poco/Data/SQLite/Connector.h"
|
||||||
|
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||||
#include "Poco/Data/Session.h"
|
#include "Poco/Data/Session.h"
|
||||||
|
#include "Poco/ActiveMethod.h"
|
||||||
|
#include "Poco/ActiveResult.h"
|
||||||
#include "Poco/String.h"
|
#include "Poco/String.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
@@ -55,8 +58,8 @@ const std::string SessionImpl::COMMIT_TRANSACTION("COMMIT");
|
|||||||
const std::string SessionImpl::ABORT_TRANSACTION("ROLLBACK");
|
const std::string SessionImpl::ABORT_TRANSACTION("ROLLBACK");
|
||||||
|
|
||||||
|
|
||||||
SessionImpl::SessionImpl(const std::string& fileName):
|
SessionImpl::SessionImpl(const std::string& fileName, std::size_t timeout):
|
||||||
Poco::Data::AbstractSessionImpl<SessionImpl>(fileName),
|
Poco::Data::AbstractSessionImpl<SessionImpl>(fileName, timeout),
|
||||||
_connector(toLower(Connector::KEY)),
|
_connector(toLower(Connector::KEY)),
|
||||||
_pDB(0),
|
_pDB(0),
|
||||||
_connected(false),
|
_connected(false),
|
||||||
@@ -133,15 +136,62 @@ bool SessionImpl::isTransactionIsolation(Poco::UInt32 ti)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SessionImpl::open()
|
class ActiveConnector
|
||||||
{
|
{
|
||||||
int rc = sqlite3_open(connectionString().c_str(), &_pDB);
|
public:
|
||||||
|
ActiveConnector(const std::string& connectString, sqlite3** ppDB):
|
||||||
|
connect(this, &ActiveConnector::connectImpl),
|
||||||
|
_connectString(connectString),
|
||||||
|
_ppDB(ppDB)
|
||||||
|
{
|
||||||
|
poco_check_ptr(_ppDB);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveMethod<int, void, ActiveConnector> connect;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActiveConnector();
|
||||||
|
|
||||||
|
inline int connectImpl()
|
||||||
|
{
|
||||||
|
return sqlite3_open(_connectString.c_str(), _ppDB);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string _connectString;
|
||||||
|
sqlite3** _ppDB;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void SessionImpl::open(const std::string& connect)
|
||||||
|
{
|
||||||
|
if (connect != connectionString())
|
||||||
|
{
|
||||||
|
if (isConnected())
|
||||||
|
throw InvalidAccessException("Session already connected");
|
||||||
|
|
||||||
|
if (!connect.empty())
|
||||||
|
setConnectionString(connect);
|
||||||
|
}
|
||||||
|
|
||||||
|
poco_assert_dbg (!connectionString().empty());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ActiveConnector connector(connectionString(), &_pDB);
|
||||||
|
ActiveResult<int> result = connector.connect();
|
||||||
|
if (!result.tryWait(getTimeout() * 1000))
|
||||||
|
throw ConnectionFailedException("Timed out.");
|
||||||
|
|
||||||
|
int rc = result.data();
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
Utility::throwException(rc);
|
Utility::throwException(rc);
|
||||||
}
|
}
|
||||||
|
} catch (SQLiteException& ex)
|
||||||
|
{
|
||||||
|
throw ConnectionFailedException(ex.displayText());
|
||||||
|
}
|
||||||
|
|
||||||
_connected = true;
|
_connected = true;
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
#include "Poco/Data/SQLite/Connector.h"
|
#include "Poco/Data/SQLite/Connector.h"
|
||||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||||
#include "Poco/Data/TypeHandler.h"
|
#include "Poco/Data/TypeHandler.h"
|
||||||
|
#include "Poco/Data/DataException.h"
|
||||||
#include "Poco/Tuple.h"
|
#include "Poco/Tuple.h"
|
||||||
#include "Poco/Any.h"
|
#include "Poco/Any.h"
|
||||||
#include "Poco/SharedPtr.h"
|
#include "Poco/SharedPtr.h"
|
||||||
@@ -71,6 +72,7 @@ using Poco::Data::Time;
|
|||||||
using Poco::Data::AbstractExtractionVec;
|
using Poco::Data::AbstractExtractionVec;
|
||||||
using Poco::Data::AbstractExtractionVecVec;
|
using Poco::Data::AbstractExtractionVecVec;
|
||||||
using Poco::Data::AbstractBindingVec;
|
using Poco::Data::AbstractBindingVec;
|
||||||
|
using Poco::Data::NotConnectedException;
|
||||||
using Poco::Tuple;
|
using Poco::Tuple;
|
||||||
using Poco::Any;
|
using Poco::Any;
|
||||||
using Poco::AnyCast;
|
using Poco::AnyCast;
|
||||||
@@ -2317,6 +2319,48 @@ void SQLiteTest::testMultipleResults()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLiteTest::testReconnect()
|
||||||
|
{
|
||||||
|
Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||||
|
|
||||||
|
session << "DROP TABLE IF EXISTS Person", now;
|
||||||
|
session << "CREATE TABLE Person (LastName VARCHAR(30),"
|
||||||
|
"FirstName VARCHAR(30),"
|
||||||
|
"Address VARCHAR(30),"
|
||||||
|
"Age INTEGER)", now;
|
||||||
|
|
||||||
|
std::string lastName = "lastName";
|
||||||
|
std::string firstName("firstName");
|
||||||
|
std::string address("Address");
|
||||||
|
int age = 133132;
|
||||||
|
int count = 0;
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
session << "INSERT INTO PERSON VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
session << "SELECT COUNT(*) FROM PERSON", into(count), now;
|
||||||
|
assert (count == 1);
|
||||||
|
|
||||||
|
assert (session.isConnected());
|
||||||
|
session.close();
|
||||||
|
assert (!session.isConnected());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
session << "SELECT LastName FROM PERSON", into(result), now;
|
||||||
|
fail ("must fail");
|
||||||
|
}
|
||||||
|
catch(NotConnectedException&){ }
|
||||||
|
assert (!session.isConnected());
|
||||||
|
|
||||||
|
session.open();
|
||||||
|
assert (session.isConnected());
|
||||||
|
session << "SELECT Age FROM PERSON", into(count), now;
|
||||||
|
assert (count == age);
|
||||||
|
assert (session.isConnected());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SQLiteTest::setUp()
|
void SQLiteTest::setUp()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -2404,6 +2448,7 @@ CppUnit::Test* SQLiteTest::suite()
|
|||||||
CppUnit_addTest(pSuite, SQLiteTest, testBindingCount);
|
CppUnit_addTest(pSuite, SQLiteTest, testBindingCount);
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testMultipleResults);
|
CppUnit_addTest(pSuite, SQLiteTest, testMultipleResults);
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testPair);
|
CppUnit_addTest(pSuite, SQLiteTest, testPair);
|
||||||
|
CppUnit_addTest(pSuite, SQLiteTest, testReconnect);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -129,6 +129,8 @@ public:
|
|||||||
void testBindingCount();
|
void testBindingCount();
|
||||||
void testMultipleResults();
|
void testMultipleResults();
|
||||||
|
|
||||||
|
void testReconnect();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
|
||||||
|
@@ -72,7 +72,8 @@ public:
|
|||||||
typedef Poco::Any (C::*PropertyGetter)(const std::string&);
|
typedef Poco::Any (C::*PropertyGetter)(const std::string&);
|
||||||
/// The getter method for a property.
|
/// The getter method for a property.
|
||||||
|
|
||||||
AbstractSessionImpl(const std::string& connectionString): SessionImpl(connectionString),
|
AbstractSessionImpl(const std::string& connectionString,
|
||||||
|
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT): SessionImpl(connectionString, timeout),
|
||||||
_storage(std::string("deque")),
|
_storage(std::string("deque")),
|
||||||
_bulk(false),
|
_bulk(false),
|
||||||
_emptyStringIsNull(false),
|
_emptyStringIsNull(false),
|
||||||
|
@@ -66,7 +66,8 @@ public:
|
|||||||
virtual const std::string& name() const = 0;
|
virtual const std::string& name() const = 0;
|
||||||
/// Returns the name associated with this connector.
|
/// Returns the name associated with this connector.
|
||||||
|
|
||||||
virtual Poco::AutoPtr<SessionImpl> createSession(const std::string& connectionString) = 0;
|
virtual Poco::AutoPtr<SessionImpl> createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout = SessionImpl::CONNECT_TIMEOUT_DEFAULT) = 0;
|
||||||
/// Create a SessionImpl object and initialize it with the given connectionString.
|
/// Create a SessionImpl object and initialize it with the given connectionString.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -62,6 +62,8 @@ POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExhaustedException, DataException)
|
|||||||
POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExistsException, DataException)
|
POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExistsException, DataException)
|
||||||
POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException)
|
POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException)
|
||||||
POCO_DECLARE_EXCEPTION(Data_API, LengthExceededException, DataException)
|
POCO_DECLARE_EXCEPTION(Data_API, LengthExceededException, DataException)
|
||||||
|
POCO_DECLARE_EXCEPTION(Data_API, ConnectionFailedException, DataException)
|
||||||
|
POCO_DECLARE_EXCEPTION(Data_API, NotConnectedException, DataException)
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
@@ -70,6 +70,7 @@ public:
|
|||||||
void begin();
|
void begin();
|
||||||
void commit();
|
void commit();
|
||||||
void rollback();
|
void rollback();
|
||||||
|
void open(const std::string& connect = "");
|
||||||
void close();
|
void close();
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
bool canTransact();
|
bool canTransact();
|
||||||
|
@@ -173,6 +173,7 @@ class Data_API Session
|
|||||||
/// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation.
|
/// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const std::size_t CONNECT_TIMEOUT_DEFAULT = SessionImpl::CONNECT_TIMEOUT_DEFAULT;
|
||||||
static const Poco::UInt32 TRANSACTION_READ_UNCOMMITTED = 0x00000001L;
|
static const Poco::UInt32 TRANSACTION_READ_UNCOMMITTED = 0x00000001L;
|
||||||
static const Poco::UInt32 TRANSACTION_READ_COMMITTED = 0x00000002L;
|
static const Poco::UInt32 TRANSACTION_READ_COMMITTED = 0x00000002L;
|
||||||
static const Poco::UInt32 TRANSACTION_REPEATABLE_READ = 0x00000004L;
|
static const Poco::UInt32 TRANSACTION_REPEATABLE_READ = 0x00000004L;
|
||||||
@@ -181,11 +182,14 @@ public:
|
|||||||
Session(Poco::AutoPtr<SessionImpl> ptrImpl);
|
Session(Poco::AutoPtr<SessionImpl> ptrImpl);
|
||||||
/// Creates the Session.
|
/// Creates the Session.
|
||||||
|
|
||||||
Session(const std::string& connector, const std::string& connectionString);
|
Session(const std::string& connector,
|
||||||
|
const std::string& connectionString,
|
||||||
|
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a new session, using the given connector (which must have
|
/// Creates a new session, using the given connector (which must have
|
||||||
/// been registered), and connectionString.
|
/// been registered), and connectionString.
|
||||||
|
|
||||||
Session(const std::string& connection);
|
Session(const std::string& connection,
|
||||||
|
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a new session, using the given connection (must be in
|
/// Creates a new session, using the given connection (must be in
|
||||||
/// "connection:///connectionString" format).
|
/// "connection:///connectionString" format).
|
||||||
|
|
||||||
@@ -211,6 +215,29 @@ public:
|
|||||||
StatementImpl* createStatementImpl();
|
StatementImpl* createStatementImpl();
|
||||||
/// Creates a StatementImpl.
|
/// Creates a StatementImpl.
|
||||||
|
|
||||||
|
void open(const std::string& connect = "");
|
||||||
|
/// Opens the session using the supplied string.
|
||||||
|
/// Can also be used with default empty string to
|
||||||
|
/// reconnect a disconnected session.
|
||||||
|
/// If the connection is not established,
|
||||||
|
/// a ConnectionFailedException is thrown.
|
||||||
|
/// Zero timout means indefinite
|
||||||
|
|
||||||
|
void close();
|
||||||
|
/// Closes the session.
|
||||||
|
|
||||||
|
bool isConnected();
|
||||||
|
/// Returns true iff session is connected, false otherwise.
|
||||||
|
|
||||||
|
void reconnect();
|
||||||
|
/// Closes the session and opens it.
|
||||||
|
|
||||||
|
void setTimeout(std::size_t timeout);
|
||||||
|
/// Sets the session timeout value.
|
||||||
|
|
||||||
|
std::size_t getTimeout() const;
|
||||||
|
/// Returns the session timeout value.
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
/// Starts a transaction.
|
/// Starts a transaction.
|
||||||
|
|
||||||
@@ -220,12 +247,6 @@ public:
|
|||||||
void rollback();
|
void rollback();
|
||||||
/// Rolls back and ends a transaction.
|
/// Rolls back and ends a transaction.
|
||||||
|
|
||||||
void close();
|
|
||||||
/// Closes the session.
|
|
||||||
|
|
||||||
bool isConnected();
|
|
||||||
/// Returns true iff session is connected, false otherwise.
|
|
||||||
|
|
||||||
bool canTransact();
|
bool canTransact();
|
||||||
/// Returns true if session has transaction capabilities.
|
/// Returns true if session has transaction capabilities.
|
||||||
|
|
||||||
@@ -296,7 +317,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Session();
|
Session();
|
||||||
|
|
||||||
Poco::AutoPtr<SessionImpl> _ptrImpl;
|
Poco::AutoPtr<SessionImpl> _pImpl;
|
||||||
StatementCreator _statementCreator;
|
StatementCreator _statementCreator;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -306,73 +327,97 @@ private:
|
|||||||
//
|
//
|
||||||
inline StatementImpl* Session::createStatementImpl()
|
inline StatementImpl* Session::createStatementImpl()
|
||||||
{
|
{
|
||||||
return _ptrImpl->createStatementImpl();
|
return _pImpl->createStatementImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void Session::begin()
|
inline void Session::open(const std::string& connect)
|
||||||
{
|
{
|
||||||
return _ptrImpl->begin();
|
_pImpl->open(connect);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void Session::commit()
|
|
||||||
{
|
|
||||||
return _ptrImpl->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void Session::rollback()
|
|
||||||
{
|
|
||||||
return _ptrImpl->rollback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void Session::close()
|
inline void Session::close()
|
||||||
{
|
{
|
||||||
_ptrImpl->close();
|
_pImpl->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Session::isConnected()
|
inline bool Session::isConnected()
|
||||||
{
|
{
|
||||||
return _ptrImpl->isConnected();
|
return _pImpl->isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Session::reconnect()
|
||||||
|
{
|
||||||
|
_pImpl->reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Session::setTimeout(std::size_t timeout)
|
||||||
|
{
|
||||||
|
_pImpl->setTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::size_t Session::getTimeout() const
|
||||||
|
{
|
||||||
|
return _pImpl->getTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Session::begin()
|
||||||
|
{
|
||||||
|
return _pImpl->begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Session::commit()
|
||||||
|
{
|
||||||
|
return _pImpl->commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Session::rollback()
|
||||||
|
{
|
||||||
|
return _pImpl->rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Session::canTransact()
|
inline bool Session::canTransact()
|
||||||
{
|
{
|
||||||
return _ptrImpl->canTransact();
|
return _pImpl->canTransact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Session::isTransaction()
|
inline bool Session::isTransaction()
|
||||||
{
|
{
|
||||||
return _ptrImpl->isTransaction();
|
return _pImpl->isTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void Session::setTransactionIsolation(Poco::UInt32 ti)
|
inline void Session::setTransactionIsolation(Poco::UInt32 ti)
|
||||||
{
|
{
|
||||||
_ptrImpl->setTransactionIsolation(ti);
|
_pImpl->setTransactionIsolation(ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline Poco::UInt32 Session::getTransactionIsolation()
|
inline Poco::UInt32 Session::getTransactionIsolation()
|
||||||
{
|
{
|
||||||
return _ptrImpl->getTransactionIsolation();
|
return _pImpl->getTransactionIsolation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Session::hasTransactionIsolation(Poco::UInt32 ti)
|
inline bool Session::hasTransactionIsolation(Poco::UInt32 ti)
|
||||||
{
|
{
|
||||||
return _ptrImpl->hasTransactionIsolation(ti);
|
return _pImpl->hasTransactionIsolation(ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Session::isTransactionIsolation(Poco::UInt32 ti)
|
inline bool Session::isTransactionIsolation(Poco::UInt32 ti)
|
||||||
{
|
{
|
||||||
return _ptrImpl->isTransactionIsolation(ti);
|
return _pImpl->isTransactionIsolation(ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -385,37 +430,37 @@ inline std::string Session::uri(const std::string& connector,
|
|||||||
|
|
||||||
inline std::string Session::uri()
|
inline std::string Session::uri()
|
||||||
{
|
{
|
||||||
return _ptrImpl->uri();
|
return _pImpl->uri();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void Session::setFeature(const std::string& name, bool state)
|
inline void Session::setFeature(const std::string& name, bool state)
|
||||||
{
|
{
|
||||||
_ptrImpl->setFeature(name, state);
|
_pImpl->setFeature(name, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Session::getFeature(const std::string& name) const
|
inline bool Session::getFeature(const std::string& name) const
|
||||||
{
|
{
|
||||||
return const_cast<SessionImpl*>(_ptrImpl.get())->getFeature(name);
|
return const_cast<SessionImpl*>(_pImpl.get())->getFeature(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void Session::setProperty(const std::string& name, const Poco::Any& value)
|
inline void Session::setProperty(const std::string& name, const Poco::Any& value)
|
||||||
{
|
{
|
||||||
_ptrImpl->setProperty(name, value);
|
_pImpl->setProperty(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline Poco::Any Session::getProperty(const std::string& name) const
|
inline Poco::Any Session::getProperty(const std::string& name) const
|
||||||
{
|
{
|
||||||
return const_cast<SessionImpl*>(_ptrImpl.get())->getProperty(name);
|
return const_cast<SessionImpl*>(_pImpl.get())->getProperty(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline SessionImpl* Session::impl()
|
inline SessionImpl* Session::impl()
|
||||||
{
|
{
|
||||||
return _ptrImpl;
|
return _pImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -83,11 +83,14 @@ public:
|
|||||||
/// Lowers the reference count for the Connector registered under that key. If the count reaches zero,
|
/// Lowers the reference count for the Connector registered under that key. If the count reaches zero,
|
||||||
/// the object is removed.
|
/// the object is removed.
|
||||||
|
|
||||||
Session create(const std::string& key, const std::string& connectionString);
|
Session create(const std::string& key,
|
||||||
|
const std::string& connectionString,
|
||||||
|
std::size_t timeout = Session::CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a Session for the given key with the connectionString. Throws an Poco:Data::UnknownDataBaseException
|
/// Creates a Session for the given key with the connectionString. Throws an Poco:Data::UnknownDataBaseException
|
||||||
/// if no Connector is registered for that key.
|
/// if no Connector is registered for that key.
|
||||||
|
|
||||||
Session create(const std::string& uri);
|
Session create(const std::string& uri,
|
||||||
|
std::size_t timeout = Session::CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a Session for the given URI (must be in key:///connectionString format).
|
/// Creates a Session for the given URI (must be in key:///connectionString format).
|
||||||
/// Throws an Poco:Data::UnknownDataBaseException if no Connector is registered for the key.
|
/// Throws an Poco:Data::UnknownDataBaseException if no Connector is registered for the key.
|
||||||
|
|
||||||
|
@@ -59,7 +59,14 @@ class Data_API SessionImpl: public Poco::RefCountedObject
|
|||||||
/// SessionImpl objects are noncopyable.
|
/// SessionImpl objects are noncopyable.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SessionImpl(const std::string& connectionString);
|
static const std::size_t CONNECT_TIMEOUT_INFINITE = 0;
|
||||||
|
/// Infinite connection/login timeout.
|
||||||
|
|
||||||
|
static const std::size_t CONNECT_TIMEOUT_DEFAULT = 30;
|
||||||
|
/// Default connection/login timeout in seconds.
|
||||||
|
|
||||||
|
SessionImpl(const std::string& connectionString,
|
||||||
|
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates the SessionImpl.
|
/// Creates the SessionImpl.
|
||||||
|
|
||||||
virtual ~SessionImpl();
|
virtual ~SessionImpl();
|
||||||
@@ -68,6 +75,29 @@ public:
|
|||||||
virtual StatementImpl* createStatementImpl() = 0;
|
virtual StatementImpl* createStatementImpl() = 0;
|
||||||
/// Creates a StatementImpl.
|
/// Creates a StatementImpl.
|
||||||
|
|
||||||
|
virtual void open(const std::string& connectionString = "") = 0;
|
||||||
|
/// Opens the session using the supplied string.
|
||||||
|
/// Can also be used with default empty string to reconnect
|
||||||
|
/// a disconnected session.
|
||||||
|
/// If the connection is not established within requested timeout
|
||||||
|
/// (specified in seconds), a ConnectionFailedException is thrown.
|
||||||
|
/// Zero timout means indefinite
|
||||||
|
|
||||||
|
virtual void close() = 0;
|
||||||
|
/// Closes the connection.
|
||||||
|
|
||||||
|
virtual bool isConnected() = 0;
|
||||||
|
/// Returns true if session is connected, false otherwise.
|
||||||
|
|
||||||
|
void setTimeout(std::size_t timeout);
|
||||||
|
/// Sets the session timeout value.
|
||||||
|
|
||||||
|
std::size_t getTimeout() const;
|
||||||
|
/// Returns the session timeout value.
|
||||||
|
|
||||||
|
void reconnect();
|
||||||
|
/// Closes the connection and opens it again.
|
||||||
|
|
||||||
virtual void begin() = 0;
|
virtual void begin() = 0;
|
||||||
/// Starts a transaction.
|
/// Starts a transaction.
|
||||||
|
|
||||||
@@ -77,12 +107,6 @@ public:
|
|||||||
virtual void rollback() = 0;
|
virtual void rollback() = 0;
|
||||||
/// Aborts a transaction.
|
/// Aborts a transaction.
|
||||||
|
|
||||||
virtual void close() = 0;
|
|
||||||
/// Closes the connection.
|
|
||||||
|
|
||||||
virtual bool isConnected() = 0;
|
|
||||||
/// Returns true if session is connected, false otherwise.
|
|
||||||
|
|
||||||
virtual bool canTransact() = 0;
|
virtual bool canTransact() = 0;
|
||||||
/// Returns true if session has transaction capabilities.
|
/// Returns true if session has transaction capabilities.
|
||||||
|
|
||||||
@@ -151,12 +175,19 @@ public:
|
|||||||
/// Throws a NotSupportedException if the requested property is
|
/// Throws a NotSupportedException if the requested property is
|
||||||
/// not supported by the underlying implementation.
|
/// not supported by the underlying implementation.
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setConnectionString(const std::string& connectionString);
|
||||||
|
/// Sets the connection string. Should only be called on
|
||||||
|
/// disconnetced sessions. Throws InvalidAccessException when called on
|
||||||
|
/// a connected session.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SessionImpl();
|
SessionImpl();
|
||||||
SessionImpl(const SessionImpl&);
|
SessionImpl(const SessionImpl&);
|
||||||
SessionImpl& operator = (const SessionImpl&);
|
SessionImpl& operator = (const SessionImpl&);
|
||||||
|
|
||||||
std::string _connectionString;
|
std::string _connectionString;
|
||||||
|
std::size_t _timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -169,6 +200,18 @@ inline const std::string& SessionImpl::connectionString()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void SessionImpl::setTimeout(std::size_t timeout)
|
||||||
|
{
|
||||||
|
_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::size_t SessionImpl::getTimeout() const
|
||||||
|
{
|
||||||
|
return _timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline std::string SessionImpl::uri(const std::string& connector,
|
inline std::string SessionImpl::uri(const std::string& connector,
|
||||||
const std::string& connectionString)
|
const std::string& connectionString)
|
||||||
{
|
{
|
||||||
|
@@ -76,6 +76,9 @@ public:
|
|||||||
Statement operator << (const T& t)
|
Statement operator << (const T& t)
|
||||||
/// Creates a Statement.
|
/// Creates a Statement.
|
||||||
{
|
{
|
||||||
|
if (!_ptrImpl->isConnected())
|
||||||
|
throw NotConnectedException(_ptrImpl->connectionString());
|
||||||
|
|
||||||
Statement stmt(_ptrImpl->createStatementImpl());
|
Statement stmt(_ptrImpl->createStatementImpl());
|
||||||
stmt << t;
|
stmt << t;
|
||||||
return stmt;
|
return stmt;
|
||||||
|
@@ -56,6 +56,8 @@ POCO_IMPLEMENT_EXCEPTION(SessionPoolExhaustedException, DataException, "No more
|
|||||||
POCO_IMPLEMENT_EXCEPTION(SessionPoolExistsException, DataException, "Session already exists in the pool")
|
POCO_IMPLEMENT_EXCEPTION(SessionPoolExistsException, DataException, "Session already exists in the pool")
|
||||||
POCO_IMPLEMENT_EXCEPTION(NoDataException, DataException, "No data found")
|
POCO_IMPLEMENT_EXCEPTION(NoDataException, DataException, "No data found")
|
||||||
POCO_IMPLEMENT_EXCEPTION(LengthExceededException, DataException, "Data too long")
|
POCO_IMPLEMENT_EXCEPTION(LengthExceededException, DataException, "Data too long")
|
||||||
|
POCO_IMPLEMENT_EXCEPTION(ConnectionFailedException, DataException, "Connection attempt failed")
|
||||||
|
POCO_IMPLEMENT_EXCEPTION(NotConnectedException, DataException, "Not connected to data source")
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
@@ -44,7 +44,8 @@ namespace Data {
|
|||||||
|
|
||||||
|
|
||||||
PooledSessionImpl::PooledSessionImpl(PooledSessionHolder* pHolder):
|
PooledSessionImpl::PooledSessionImpl(PooledSessionHolder* pHolder):
|
||||||
SessionImpl(pHolder->session()->connectionString()),
|
SessionImpl(pHolder->session()->connectionString(),
|
||||||
|
pHolder->session()->getTimeout()),
|
||||||
_pHolder(pHolder, true)
|
_pHolder(pHolder, true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -122,6 +123,12 @@ void PooledSessionImpl::rollback()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PooledSessionImpl::open(const std::string& connect)
|
||||||
|
{
|
||||||
|
access()->open(connect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PooledSessionImpl::close()
|
void PooledSessionImpl::close()
|
||||||
{
|
{
|
||||||
if (_pHolder)
|
if (_pHolder)
|
||||||
|
@@ -45,30 +45,33 @@ namespace Poco {
|
|||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
Session::Session(Poco::AutoPtr<SessionImpl> ptrImpl):
|
Session::Session(Poco::AutoPtr<SessionImpl> pImpl):
|
||||||
_ptrImpl(ptrImpl),
|
_pImpl(pImpl),
|
||||||
_statementCreator(ptrImpl)
|
_statementCreator(pImpl)
|
||||||
{
|
{
|
||||||
poco_check_ptr (ptrImpl.get());
|
poco_check_ptr (pImpl.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Session::Session(const std::string& connector, const std::string& connectionString)
|
Session::Session(const std::string& connector,
|
||||||
|
const std::string& connectionString,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
Session newSession(SessionFactory::instance().create(connector, connectionString));
|
Session newSession(SessionFactory::instance().create(connector, connectionString, timeout));
|
||||||
swap(newSession);
|
swap(newSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Session::Session(const std::string& connection)
|
Session::Session(const std::string& connection,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
Session newSession(SessionFactory::instance().create(connection));
|
Session newSession(SessionFactory::instance().create(connection, timeout));
|
||||||
swap(newSession);
|
swap(newSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Session::Session(const Session& other): _ptrImpl(other._ptrImpl),
|
Session::Session(const Session& other): _pImpl(other._pImpl),
|
||||||
_statementCreator(other._ptrImpl)
|
_statementCreator(other._pImpl)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +93,7 @@ void Session::swap(Session& other)
|
|||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(_statementCreator, other._statementCreator);
|
swap(_statementCreator, other._statementCreator);
|
||||||
swap(_ptrImpl, other._ptrImpl);
|
swap(_pImpl, other._pImpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -81,21 +81,24 @@ void SessionFactory::remove(const std::string& key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Session SessionFactory::create(const std::string& key, const std::string& connectionString)
|
Session SessionFactory::create(const std::string& key,
|
||||||
|
const std::string& connectionString,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||||
Connectors::iterator it = _connectors.find(toLower(key));
|
Connectors::iterator it = _connectors.find(toLower(key));
|
||||||
poco_assert (_connectors.end() != it);
|
poco_assert (_connectors.end() != it);
|
||||||
|
|
||||||
return Session(it->second.ptrSI->createSession(connectionString));
|
return Session(it->second.ptrSI->createSession(connectionString, timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Session SessionFactory::create(const std::string& uri)
|
Session SessionFactory::create(const std::string& uri,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
URI u(uri);
|
URI u(uri);
|
||||||
poco_assert (!u.getPath().empty());
|
poco_assert (!u.getPath().empty());
|
||||||
return create(u.getScheme(), u.getPath().substr(1));
|
return create(u.getScheme(), u.getPath().substr(1), timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -35,14 +35,16 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/Data/SessionImpl.h"
|
#include "Poco/Data/SessionImpl.h"
|
||||||
|
#include "Poco/Exception.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
SessionImpl::SessionImpl(const std::string& connectionString):
|
SessionImpl::SessionImpl(const std::string& connectionString, std::size_t timeout):
|
||||||
_connectionString(connectionString)
|
_connectionString(connectionString),
|
||||||
|
_timeout(timeout)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,4 +54,21 @@ SessionImpl::~SessionImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SessionImpl::reconnect()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SessionImpl::setConnectionString(const std::string& connectionString)
|
||||||
|
{
|
||||||
|
if (isConnected())
|
||||||
|
throw Poco::InvalidAccessException("Can not change connection string on connected session."
|
||||||
|
" Close the session first.");
|
||||||
|
|
||||||
|
_connectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#include "Poco/SharedPtr.h"
|
#include "Poco/SharedPtr.h"
|
||||||
#include "Poco/DateTime.h"
|
#include "Poco/DateTime.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
|
#include "Poco/Data/DataException.h"
|
||||||
|
|
||||||
|
|
||||||
using Poco::icompare;
|
using Poco::icompare;
|
||||||
@@ -74,6 +75,9 @@ StatementImpl::StatementImpl(SessionImpl& rSession):
|
|||||||
_bulkBinding(BULK_UNDEFINED),
|
_bulkBinding(BULK_UNDEFINED),
|
||||||
_bulkExtraction(BULK_UNDEFINED)
|
_bulkExtraction(BULK_UNDEFINED)
|
||||||
{
|
{
|
||||||
|
if (!_rSession.isConnected())
|
||||||
|
throw NotConnectedException(_rSession.connectionString());
|
||||||
|
|
||||||
_extractors.resize(1);
|
_extractors.resize(1);
|
||||||
_columnsExtracted.resize(1, 0);
|
_columnsExtracted.resize(1, 0);
|
||||||
}
|
}
|
||||||
@@ -87,6 +91,13 @@ StatementImpl::~StatementImpl()
|
|||||||
std::size_t StatementImpl::execute()
|
std::size_t StatementImpl::execute()
|
||||||
{
|
{
|
||||||
resetExtraction();
|
resetExtraction();
|
||||||
|
|
||||||
|
if (!_rSession.isConnected())
|
||||||
|
{
|
||||||
|
_state = ST_DONE;
|
||||||
|
throw NotConnectedException(_rSession.connectionString());
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t lim = 0;
|
std::size_t lim = 0;
|
||||||
if (_lowerLimit > _extrLimit.value())
|
if (_lowerLimit > _extrLimit.value())
|
||||||
throw LimitException("Illegal Statement state. Upper limit must not be smaller than the lower limit.");
|
throw LimitException("Illegal Statement state. Upper limit must not be smaller than the lower limit.");
|
||||||
|
@@ -53,9 +53,10 @@ Connector::~Connector()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString)
|
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout)
|
||||||
{
|
{
|
||||||
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString));
|
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -60,7 +60,8 @@ public:
|
|||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
/// Returns the name associated with this connector.
|
/// Returns the name associated with this connector.
|
||||||
|
|
||||||
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
|
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
|
||||||
|
std::size_t timeout = SessionImpl::CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates a test SessionImpl object and initializes it with the given connectionString.
|
/// Creates a test SessionImpl object and initializes it with the given connectionString.
|
||||||
|
|
||||||
static void addToFactory();
|
static void addToFactory();
|
||||||
|
@@ -42,6 +42,7 @@
|
|||||||
#include "Poco/Data/Date.h"
|
#include "Poco/Data/Date.h"
|
||||||
#include "Poco/Data/Time.h"
|
#include "Poco/Data/Time.h"
|
||||||
#include "Poco/Data/SimpleRowFormatter.h"
|
#include "Poco/Data/SimpleRowFormatter.h"
|
||||||
|
#include "Poco/Data/DataException.h"
|
||||||
#include "Connector.h"
|
#include "Connector.h"
|
||||||
#include "Poco/BinaryReader.h"
|
#include "Poco/BinaryReader.h"
|
||||||
#include "Poco/BinaryWriter.h"
|
#include "Poco/BinaryWriter.h"
|
||||||
@@ -89,6 +90,7 @@ using Poco::Data::AbstractExtractionVec;
|
|||||||
using Poco::Data::AbstractExtractionVecVec;
|
using Poco::Data::AbstractExtractionVecVec;
|
||||||
using Poco::Data::AbstractBinding;
|
using Poco::Data::AbstractBinding;
|
||||||
using Poco::Data::AbstractBindingVec;
|
using Poco::Data::AbstractBindingVec;
|
||||||
|
using Poco::Data::NotConnectedException;
|
||||||
|
|
||||||
|
|
||||||
DataTest::DataTest(const std::string& name): CppUnit::TestCase(name)
|
DataTest::DataTest(const std::string& name): CppUnit::TestCase(name)
|
||||||
@@ -110,6 +112,10 @@ void DataTest::testSession()
|
|||||||
assert ("cs" == sess.impl()->connectionString());
|
assert ("cs" == sess.impl()->connectionString());
|
||||||
assert ("test:///cs" == sess.uri());
|
assert ("test:///cs" == sess.uri());
|
||||||
|
|
||||||
|
assert (sess.getTimeout() == Session::CONNECT_TIMEOUT_DEFAULT);
|
||||||
|
sess.setTimeout(123);
|
||||||
|
assert (sess.getTimeout() == 123);
|
||||||
|
|
||||||
Session sess2(SessionFactory::instance().create("TeSt:///Cs"));
|
Session sess2(SessionFactory::instance().create("TeSt:///Cs"));
|
||||||
assert ("test" == sess2.impl()->connectorName());
|
assert ("test" == sess2.impl()->connectorName());
|
||||||
assert ("Cs" == sess2.impl()->connectionString());
|
assert ("Cs" == sess2.impl()->connectionString());
|
||||||
@@ -122,6 +128,36 @@ void DataTest::testSession()
|
|||||||
std::string str;
|
std::string str;
|
||||||
Statement stmt = (sess << "SELECT * FROM Strings", into(str), limit(50));
|
Statement stmt = (sess << "SELECT * FROM Strings", into(str), limit(50));
|
||||||
stmt.execute();
|
stmt.execute();
|
||||||
|
|
||||||
|
sess.close();
|
||||||
|
assert (!sess.getFeature("connected"));
|
||||||
|
assert (!sess.isConnected());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stmt.execute();
|
||||||
|
fail ("must fail");
|
||||||
|
} catch (NotConnectedException&) { }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sess << "SELECT * FROM Strings", now;
|
||||||
|
fail ("must fail");
|
||||||
|
} catch (NotConnectedException&) { }
|
||||||
|
|
||||||
|
sess.open();
|
||||||
|
assert (sess.getFeature("connected"));
|
||||||
|
assert (sess.isConnected());
|
||||||
|
|
||||||
|
sess << "SELECT * FROM Strings", now;
|
||||||
|
stmt.execute();
|
||||||
|
|
||||||
|
sess.reconnect();
|
||||||
|
assert (sess.getFeature("connected"));
|
||||||
|
assert (sess.isConnected());
|
||||||
|
|
||||||
|
sess << "SELECT * FROM Strings", now;
|
||||||
|
stmt.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -40,8 +40,8 @@ namespace Data {
|
|||||||
namespace Test {
|
namespace Test {
|
||||||
|
|
||||||
|
|
||||||
SessionImpl::SessionImpl(const std::string& init):
|
SessionImpl::SessionImpl(const std::string& init, std::size_t timeout):
|
||||||
Poco::Data::AbstractSessionImpl<SessionImpl>(init),
|
Poco::Data::AbstractSessionImpl<SessionImpl>(init, timeout),
|
||||||
_f(false),
|
_f(false),
|
||||||
_connected(true)
|
_connected(true)
|
||||||
{
|
{
|
||||||
@@ -60,6 +60,24 @@ SessionImpl::~SessionImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SessionImpl::open(const std::string& connectionString)
|
||||||
|
{
|
||||||
|
_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SessionImpl::close()
|
||||||
|
{
|
||||||
|
_connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SessionImpl::isConnected()
|
||||||
|
{
|
||||||
|
return _connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
||||||
{
|
{
|
||||||
return new TestStatementImpl(*this);
|
return new TestStatementImpl(*this);
|
||||||
@@ -81,18 +99,6 @@ void SessionImpl::rollback()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SessionImpl::close()
|
|
||||||
{
|
|
||||||
_connected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool SessionImpl::isConnected()
|
|
||||||
{
|
|
||||||
return _connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool SessionImpl::canTransact()
|
bool SessionImpl::canTransact()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@@ -50,7 +50,8 @@ class SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
|
|||||||
/// A no-op implementation of SessionImpl for testing.
|
/// A no-op implementation of SessionImpl for testing.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SessionImpl(const std::string& init);
|
SessionImpl(const std::string& init,
|
||||||
|
std::size_t timeout = CONNECT_TIMEOUT_DEFAULT);
|
||||||
/// Creates the SessionImpl. Opens a connection to the database.
|
/// Creates the SessionImpl. Opens a connection to the database.
|
||||||
|
|
||||||
~SessionImpl();
|
~SessionImpl();
|
||||||
@@ -59,6 +60,16 @@ public:
|
|||||||
Poco::Data::StatementImpl* createStatementImpl();
|
Poco::Data::StatementImpl* createStatementImpl();
|
||||||
/// Returns an test StatementImpl.
|
/// Returns an test StatementImpl.
|
||||||
|
|
||||||
|
void open(const std::string& connectionString = "");
|
||||||
|
/// Opens the session.
|
||||||
|
|
||||||
|
void close();
|
||||||
|
/// Closes the session.
|
||||||
|
|
||||||
|
bool isConnected();
|
||||||
|
/// Returns true if session is connected to the database,
|
||||||
|
/// false otherwise.
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
/// Starts a transaction.
|
/// Starts a transaction.
|
||||||
|
|
||||||
@@ -68,13 +79,6 @@ public:
|
|||||||
void rollback();
|
void rollback();
|
||||||
/// Aborts a transaction.
|
/// Aborts a transaction.
|
||||||
|
|
||||||
void close();
|
|
||||||
/// Closes the session.
|
|
||||||
|
|
||||||
bool isConnected();
|
|
||||||
/// Returns true if session is connected to the database,
|
|
||||||
/// false otherwise.
|
|
||||||
|
|
||||||
bool canTransact();
|
bool canTransact();
|
||||||
/// Returns true if session has transaction capabilities.
|
/// Returns true if session has transaction capabilities.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user