[SF 2505290] DB connection as URI (MySQL not tested!)

This commit is contained in:
Aleksandar Fabijanic 2009-01-13 19:51:48 +00:00
parent 8abc90f989
commit b38f5ce99c
25 changed files with 199 additions and 47 deletions

View File

@ -98,12 +98,15 @@ public:
Poco::Any getInsertId(const std::string&);
/// Get insert id
SessionHandle& handle();
// Get handle
const std::string& connectorName();
/// Returns the name of the connector.
private:
std::string _connector;
SessionHandle _mysql;
bool _connected;
int _inTransaction;
@ -124,11 +127,19 @@ inline Poco::Any SessionImpl::getInsertId(const std::string&)
return Poco::Any(Poco::UInt64(mysql_insert_id(_mysql)));
}
inline SessionHandle& SessionImpl::handle()
{
return _mysql;
}
inline const std::string& SessionImpl::connectorName()
{
return _connector;
}
} } } // namespace Poco::Data::MySQL

View File

@ -47,7 +47,7 @@ namespace Data {
namespace MySQL {
std::string Connector::KEY("MySQL");
std::string Connector::KEY("mysql");
Connector::Connector()

View File

@ -37,6 +37,7 @@
#include "Poco/Data/MySQL/SessionImpl.h"
#include "Poco/Data/MySQL/MySQLStatementImpl.h"
#include "Poco/NumberParser.h"
#include "Poco/String.h"
namespace
@ -58,7 +59,11 @@ namespace Data {
namespace MySQL {
SessionImpl::SessionImpl(const std::string& connectionString) : _mysql(0), _connected(false), _inTransaction(0)
SessionImpl::SessionImpl(const std::string& connectionString) :
Poco::Data::AbstractSessionImpl<SessionImpl>(toLower(connectionString)),
_mysql(0),
_connected(false),
_inTransaction(0)
{
addProperty("insertId",
&SessionImpl::setInsertId,

View File

@ -79,6 +79,7 @@ public:
///
/// inlines
///
inline const std::string& Connector::name() const
{
return KEY;

View File

@ -41,6 +41,7 @@
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Connector.h"
#include "Poco/Data/ODBC/TypeInfo.h"
#include "Poco/Data/ODBC/Binder.h"
#include "Poco/Data/ODBC/Handle.h"
@ -93,6 +94,9 @@ public:
bool isTransaction();
/// Returns true iff a transaction is in progress.
const std::string& connectorName();
/// Returns the name of the connector.
bool canTransact();
/// Returns true if connection is transaction-capable.
@ -140,10 +144,9 @@ private:
void checkError(SQLRETURN rc, const std::string& msg="");
std::string _connect;
std::string _connector;
const ConnectionHandle _db;
Poco::Any _maxFieldSize;
bool _enforceCapability;
bool _autoBind;
bool _autoExtract;
TypeInfo _dataTypes;
@ -228,6 +231,12 @@ inline bool SessionImpl::isAutoExtract(const std::string& name)
}
inline const std::string& SessionImpl::connectorName()
{
return _connector;
}
} } } // namespace Poco::Data::ODBC

View File

@ -44,7 +44,7 @@ namespace Data {
namespace ODBC {
const std::string Connector::KEY("ODBC");
const std::string Connector::KEY("odbc");
Connector::Connector()

View File

@ -39,6 +39,7 @@
#include "Poco/Data/ODBC/ODBCStatementImpl.h"
#include "Poco/Data/ODBC/Error.h"
#include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/String.h"
#include <sqlext.h>
@ -51,12 +52,11 @@ SessionImpl::SessionImpl(const std::string& connect,
Poco::Any maxFieldSize,
bool enforceCapability,
bool autoBind,
bool autoExtract):
_connect(connect),
_maxFieldSize(maxFieldSize),
_enforceCapability(enforceCapability),
_autoBind(autoBind),
_autoExtract(autoExtract)
bool autoExtract): Poco::Data::AbstractSessionImpl<SessionImpl>(connect),
_connector(toLower(Connector::KEY)),
_maxFieldSize(maxFieldSize),
_autoBind(autoBind),
_autoExtract(autoExtract)
{
setFeature("bulk", true);
open();
@ -87,7 +87,7 @@ void SessionImpl::open()
if (Utility::isError(Poco::Data::ODBC::SQLDriverConnect(_db
, NULL
,(SQLCHAR*) _connect.c_str()
,(SQLCHAR*) connectionString().c_str()
,(SQLSMALLINT) SQL_NTS
, connectOutput
, sizeof(connectOutput)

View File

@ -86,11 +86,14 @@ public:
bool isTransaction();
/// Returns true iff a transaction is in progress.
const std::string& connectorName();
/// Returns the name of the connector.
private:
void open();
/// Opens a connection to the Database.
std::string _dbFileName;
std::string _connector;
sqlite3* _pDB;
bool _connected;
bool _isTransaction;
@ -110,6 +113,12 @@ inline bool SessionImpl::isTransaction()
}
inline const std::string& SessionImpl::connectorName()
{
return _connector;
}
} } } // namespace Poco::Data::SQLite

View File

@ -45,7 +45,7 @@ namespace Data {
namespace SQLite {
const std::string Connector::KEY("SQLite");
const std::string Connector::KEY("sqlite");
Connector::Connector()

View File

@ -37,6 +37,8 @@
#include "Poco/Data/SQLite/SessionImpl.h"
#include "Poco/Data/SQLite/Utility.h"
#include "Poco/Data/SQLite/SQLiteStatementImpl.h"
#include "Poco/Data/SQLite/Connector.h"
#include "Poco/String.h"
#include "sqlite3.h"
#include <cstdlib>
@ -52,7 +54,8 @@ const std::string SessionImpl::ABORT_TRANSACTION("ROLLBACK");
SessionImpl::SessionImpl(const std::string& fileName):
_dbFileName(fileName),
Poco::Data::AbstractSessionImpl<SessionImpl>(fileName),
_connector(toLower(Connector::KEY)),
_pDB(0),
_connected(false),
_isTransaction(false)
@ -103,7 +106,7 @@ void SessionImpl::rollback()
void SessionImpl::open()
{
int rc = sqlite3_open(_dbFileName.c_str(), &_pDB);
int rc = sqlite3_open(connectionString().c_str(), &_pDB);
if (rc != 0)
{

View File

@ -72,7 +72,8 @@ public:
typedef Poco::Any (C::*PropertyGetter)(const std::string&);
/// The getter method for a property.
AbstractSessionImpl(): _storage(std::string("deque")),
AbstractSessionImpl(const std::string& connectionString): SessionImpl(connectionString),
_storage(std::string("deque")),
_bulk(false),
_emptyStringIsNull(false),
_forceEmptyString(false)

View File

@ -73,6 +73,7 @@ public:
void close();
bool isConnected();
bool isTransaction();
const std::string& connectorName();
void setFeature(const std::string& name, bool state);
bool getFeature(const std::string& name);
void setProperty(const std::string& name, const Poco::Any& value);

View File

@ -180,6 +180,10 @@ public:
/// Creates a new session, using the given connector (which must have
/// been registered), and connectionString.
Session(const std::string& connection);
/// Creates a new session, using the given connection (must be in
/// "connection:///connectionString" format).
Session(const Session&);
/// Creates a session by copying another one.
@ -220,6 +224,14 @@ public:
bool isTransaction();
/// Returns true iff a transaction is in progress, false otherwise.
std::string uri();
/// Returns the URI for this session.
static std::string uri(const std::string& connector,
const std::string& connectionString);
/// Utility function that teturns the URI formatted from supplied
/// arguments as "connector://connectionString".
void setFeature(const std::string& name, bool state);
/// Set the state of a feature.
///
@ -312,6 +324,19 @@ inline bool Session::isTransaction()
}
inline std::string Session::uri(const std::string& connector,
const std::string& connectionString)
{
return SessionImpl::uri(connector, connectionString);
}
inline std::string Session::uri()
{
return _ptrImpl->uri();
}
inline void Session::setFeature(const std::string& name, bool state)
{
_ptrImpl->setFeature(name, state);

View File

@ -87,6 +87,10 @@ public:
/// Creates a Session for the given key with the connectionString. Throws an Poco:Data::UnknownDataBaseException
/// if no Connector is registered for that key.
Session create(const std::string& uri);
/// 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.
private:
SessionFactory();
~SessionFactory();

View File

@ -42,6 +42,8 @@
#include "Poco/Data/Data.h"
#include "Poco/RefCountedObject.h"
#include "Poco/String.h"
#include "Poco/Format.h"
#include "Poco/Any.h"
@ -57,7 +59,7 @@ class Data_API SessionImpl: public Poco::RefCountedObject
/// SessionImpl objects are noncopyable.
{
public:
SessionImpl();
SessionImpl(const std::string& connectionString);
/// Creates the SessionImpl.
virtual ~SessionImpl();
@ -84,6 +86,18 @@ public:
virtual bool isTransaction() = 0;
/// Returns true iff a transaction is a transaction is in progress, false otherwise.
virtual const std::string& connectorName() = 0;
/// Returns the name of the connector.
const std::string& connectionString();
/// Returns the connection string.
static std::string uri(const std::string& connector, const std::string& connectionString);
/// Returns formatted URI.
std::string uri();
/// Returns the URI for this session.
virtual void setFeature(const std::string& name, bool state) = 0;
/// Set the state of a feature.
///
@ -121,11 +135,36 @@ public:
/// not supported by the underlying implementation.
private:
SessionImpl();
SessionImpl(const SessionImpl&);
SessionImpl& operator = (const SessionImpl&);
std::string _connectionString;
};
//
// inlines
//
inline const std::string& SessionImpl::connectionString()
{
return _connectionString;
}
inline std::string SessionImpl::uri(const std::string& connector,
const std::string& connectionString)
{
return format("%s:///%s", toLower(connector), connectionString);
}
inline std::string SessionImpl::uri()
{
return uri(connectorName(), connectionString());
}
} } // namespace Poco::Data

View File

@ -89,12 +89,12 @@ class Data_API SessionPool: public RefCountedObject
/// ...
{
public:
SessionPool(const std::string& sessionKey,
SessionPool(const std::string& connector,
const std::string& connectionString,
int minSessions = 1,
int maxSessions = 32,
int idleTime = 60);
/// Creates the SessionPool for sessions with the given sessionKey
/// Creates the SessionPool for sessions with the given connector
/// and connectionString.
///
/// The pool allows for at most maxSessions sessions to be created.
@ -136,9 +136,9 @@ public:
std::string name() const;
/// Returns the name for this pool.
static std::string name(const std::string sessionKey,
static std::string name(const std::string& connector,
const std::string& connectionString);
/// Returns the name formatted from supplied arguments as "sessionKey://connectionString".
/// Returns the name formatted from supplied arguments as "connector://connectionString".
void setFeature(const std::string& name, bool state);
/// Sets feature for all the sessions.
@ -172,7 +172,7 @@ private:
void closeAll(SessionList& sessionList);
std::string _sessionKey;
std::string _connector;
std::string _connectionString;
int _minSessions;
int _maxSessions;
@ -191,16 +191,16 @@ private:
};
inline std::string SessionPool::name(const std::string sessionKey,
inline std::string SessionPool::name(const std::string& connector,
const std::string& connectionString)
{
return format("%s://%s", sessionKey, connectionString);
return Session::uri(connector, connectionString);
}
inline std::string SessionPool::name() const
{
return name(_sessionKey, _connectionString);
return name(_connector, _connectionString);
}

View File

@ -44,6 +44,7 @@ namespace Data {
PooledSessionImpl::PooledSessionImpl(PooledSessionHolder* pHolder):
SessionImpl(pHolder->session()->connectionString()),
_pHolder(pHolder, true)
{
}
@ -113,6 +114,12 @@ void PooledSessionImpl::close()
}
const std::string& PooledSessionImpl::connectorName()
{
return access()->connectorName();
}
void PooledSessionImpl::setFeature(const std::string& name, bool state)
{
access()->setFeature(name, state);

View File

@ -36,6 +36,8 @@
#include "Poco/Data/Session.h"
#include "Poco/Data/SessionFactory.h"
#include "Poco/String.h"
#include "Poco/URI.h"
#include <algorithm>
@ -58,8 +60,14 @@ Session::Session(const std::string& connector, const std::string& connectionStri
}
Session::Session(const Session& other):
_ptrImpl(other._ptrImpl),
Session::Session(const std::string& connection)
{
Session newSession(SessionFactory::instance().create(connection));
swap(newSession);
}
Session::Session(const Session& other): _ptrImpl(other._ptrImpl),
_statementCreator(other._ptrImpl)
{
}

View File

@ -35,6 +35,8 @@
#include "Poco/Data/SessionFactory.h"
#include "Poco/URI.h"
#include "Poco/String.h"
namespace Poco {
@ -62,36 +64,41 @@ void SessionFactory::add(Connector* pIn)
{
Poco::FastMutex::ScopedLock lock(_mutex);
SessionInfo info(pIn);
std::pair<Connectors::iterator, bool> res = _connectors.insert(std::make_pair(pIn->name(), info));
if (!res.second)
{
res.first->second.cnt++;
}
std::pair<Connectors::iterator, bool> res =
_connectors.insert(std::make_pair(toLower(pIn->name()), info));
if (!res.second) res.first->second.cnt++;
}
void SessionFactory::remove(const std::string& key)
{
Poco::FastMutex::ScopedLock lock(_mutex);
Connectors::iterator it = _connectors.find(key);
Connectors::iterator it = _connectors.find(toLower(key));
poco_assert (_connectors.end() != it);
--(it->second.cnt);
if (it->second.cnt == 0)
_connectors.erase(it);
if (it->second.cnt == 0) _connectors.erase(it);
}
Session SessionFactory::create(const std::string& key, const std::string& connectionString)
{
Poco::FastMutex::ScopedLock lock(_mutex);
Connectors::iterator it = _connectors.find(key);
Connectors::iterator it = _connectors.find(toLower(key));
poco_assert (_connectors.end() != it);
return Session(it->second.ptrSI->createSession(connectionString));
}
Session SessionFactory::create(const std::string& uri)
{
URI u(uri);
poco_assert (!u.getPath().empty());
return create(u.getScheme(), u.getPath().substr(1));
}
SessionFactory::SessionInfo::SessionInfo(Connector* pSI):
cnt(1),
ptrSI(pSI)

View File

@ -41,7 +41,8 @@ namespace Poco {
namespace Data {
SessionImpl::SessionImpl()
SessionImpl::SessionImpl(const std::string& connectionString):
_connectionString(connectionString)
{
}

View File

@ -44,8 +44,8 @@ namespace Poco {
namespace Data {
SessionPool::SessionPool(const std::string& sessionKey, const std::string& connectionString, int minSessions, int maxSessions, int idleTime):
_sessionKey(sessionKey),
SessionPool::SessionPool(const std::string& connector, const std::string& connectionString, int minSessions, int maxSessions, int idleTime):
_connector(connector),
_connectionString(connectionString),
_minSessions(minSessions),
_maxSessions(maxSessions),
@ -76,7 +76,7 @@ Session SessionPool::get()
{
if (_nSessions < _maxSessions)
{
Session newSession(SessionFactory::instance().create(_sessionKey, _connectionString));
Session newSession(SessionFactory::instance().create(_connector, _connectionString));
FeatureMap::Iterator fmIt = _featureMap.begin();
FeatureMap::Iterator fmEnd = _featureMap.end();
@ -90,7 +90,7 @@ Session SessionPool::get()
_idleSessions.push_front(pHolder);
++_nSessions;
}
else throw SessionPoolExhaustedException(_sessionKey, _connectionString);
else throw SessionPoolExhaustedException(_connector, _connectionString);
}
PooledSessionHolderPtr pHolder(_idleSessions.front());

View File

@ -106,6 +106,15 @@ DataTest::~DataTest()
void DataTest::testSession()
{
Session sess(SessionFactory::instance().create("test", "cs"));
assert ("test" == sess.impl()->connectorName());
assert ("cs" == sess.impl()->connectionString());
assert ("test:///cs" == sess.uri());
Session sess2(SessionFactory::instance().create("TeSt:///Cs"));
assert ("test" == sess2.impl()->connectorName());
assert ("Cs" == sess2.impl()->connectionString());
assert ("test:///Cs" == sess2.uri());
sess << "DROP TABLE IF EXISTS Test", now;
int count;
sess << "SELECT COUNT(*) FROM PERSON", into(count), now;

View File

@ -32,6 +32,7 @@
#include "SessionImpl.h"
#include "TestStatementImpl.h"
#include "Connector.h"
namespace Poco {
@ -40,6 +41,7 @@ namespace Test {
SessionImpl::SessionImpl(const std::string& init):
Poco::Data::AbstractSessionImpl<SessionImpl>(init),
_f(false),
_connected(true)
{
@ -97,6 +99,12 @@ bool SessionImpl::isTransaction()
}
const std::string& SessionImpl::connectorName()
{
return Connector::KEY;
}
bool SessionImpl::getConnected(const std::string& name)
{
return _connected;

View File

@ -78,6 +78,9 @@ public:
bool isTransaction();
/// Returns true iff a transaction is a transaction is in progress, false otherwise.
const std::string& connectorName();
/// Returns the name of the connector.
void setConnected(const std::string& name, bool value);
bool getConnected(const std::string& name);
/// Sets/gets the connected property.
@ -90,9 +93,10 @@ public:
Poco::Any getP(const std::string& name);
private:
bool _f;
Poco::Any _p;
bool _connected;
bool _f;
Poco::Any _p;
bool _connected;
std::string _connectionString;
};

View File

@ -238,7 +238,7 @@ void SessionPoolTest::testSessionPoolContainer()
spc.add("test", "cs");
spc.add("test", "cs");//duplicate request, must be silently ignored
assert (1 == spc.count());
spc.remove("test://cs");
spc.remove("test:///cs");
assert (0 == spc.count());
try { spc.get("test"); fail ("must fail"); }
catch (NotFoundException&) { }