1
0
mirror of https://github.com/pocoproject/poco.git synced 2025-04-01 01:16:55 +02:00
2022-05-17 07:33:50 +02:00

261 lines
5.5 KiB
C++

//
// SessionImpl.cpp
//
// Library: Data/PostgreSQL
// Package: PostgreSQL
// Module: SessionImpl
//
// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/PostgreSQL/SessionImpl.h"
#include "Poco/Data/PostgreSQL/PostgreSQLException.h"
#include "Poco/Data/PostgreSQL/PostgreSQLStatementImpl.h"
#include "Poco/Data/PostgreSQL/PostgreSQLTypes.h"
#include "Poco/Data/Session.h"
#include "Poco/NumberParser.h"
#include "Poco/String.h"
#include <map>
namespace
{
std::string copyStripped(std::string::const_iterator aFromStringCItr, std::string::const_iterator aToStringCItr)
{
// skip leading spaces
while ((aFromStringCItr != aToStringCItr) && isspace(*aFromStringCItr)) aFromStringCItr++;
// skip trailing spaces
while ((aFromStringCItr != aToStringCItr) && isspace(*(aToStringCItr - 1))) aToStringCItr--;
return std::string(aFromStringCItr, aToStringCItr);
}
std::string createConnectionStringFromOptionsMap(const std::map <std::string, std::string> anOptionsMap)
{
std::string connectionString;
for (auto citr = anOptionsMap.begin(); citr != anOptionsMap.end(); ++citr)
{
connectionString.append(citr->first);
connectionString.append("=");
connectionString.append(citr->second);
connectionString.append(" ");
}
return connectionString;
}
}
namespace Poco {
namespace Data {
namespace PostgreSQL {
SessionImpl::SessionImpl(const std::string& aConnectionString, std::size_t aLoginTimeout):
Poco::Data::AbstractSessionImpl<SessionImpl>(aConnectionString, aLoginTimeout),
_connectorName("postgresql")
{
setProperty("handle", static_cast<SessionHandle*>(&_sessionHandle));
setConnectionTimeout(CONNECTION_TIMEOUT_DEFAULT);
open();
}
SessionImpl::~SessionImpl()
{
try
{
close();
}
catch (...)
{
}
}
void SessionImpl::setConnectionTimeout(std::size_t aTimeout)
{
_timeout = aTimeout;
}
void SessionImpl::open(const std::string& aConnectionString)
{
if (connectionString() != aConnectionString)
{
if (isConnected())
{
throw ConnectionException("Session already connected");
}
if (!aConnectionString.empty())
{
setConnectionString(aConnectionString);
}
}
poco_assert_dbg (!connectionString().empty());
unsigned int timeout = static_cast<unsigned int>(getLoginTimeout());
// PostgreSQL connections can use environment variables for connection parameters.
// As such it is not an error if they are not part of the connection string
std::map <std::string, std::string> optionsMap;
// Default values
optionsMap["connect_timeout"] = Poco::NumberFormatter::format(timeout);
const std::string& connString = connectionString();
for (std::string::const_iterator start = connString.begin();;)
{
std::string::const_iterator finish = std::find(start, connString.end(), ' '); // space is the separator between keyword=value pairs
std::string::const_iterator middle = std::find(start, finish, '=');
if (middle == finish)
{
throw PostgreSQLException("create session: bad connection string format, cannot find '='");
}
optionsMap[ copyStripped(start, middle) ] = copyStripped(middle + 1, finish);
if ((finish == connString.end()) || (finish + 1 == connString.end())) break;
start = finish + 1;
}
// Real connect
_sessionHandle.connect(createConnectionStringFromOptionsMap(optionsMap));
addFeature("autoCommit",
&SessionImpl::setAutoCommit,
&SessionImpl::isAutoCommit);
addFeature("asynchronousCommit",
&SessionImpl::setAutoCommit,
&SessionImpl::isAutoCommit);
addFeature("binaryExtraction",
&SessionImpl::setBinaryExtraction,
&SessionImpl::isBinaryExtraction);
}
void SessionImpl::close()
{
if (isConnected())
{
_sessionHandle.disconnect();
}
}
void SessionImpl::reset()
{
}
bool SessionImpl::isConnected() const
{
return _sessionHandle.isConnected();
}
StatementImpl::Ptr SessionImpl::createStatementImpl()
{
return new PostgreSQLStatementImpl (*this);
}
bool SessionImpl::isTransaction() const
{
return _sessionHandle.isTransaction();
}
void SessionImpl::begin()
{
if (isTransaction())
{
throw Poco::InvalidAccessException("Already in transaction.");
}
_sessionHandle.startTransaction();
}
void SessionImpl::commit()
{
// Not an error to issue a COMMIT without a preceding BEGIN
_sessionHandle.commit();
}
void SessionImpl::rollback()
{
// Not an error to issue a ROLLBACK without a preceding BEGIN
_sessionHandle.rollback();
}
void SessionImpl::setAutoCommit(const std::string&, bool aValue)
{
_sessionHandle.setAutoCommit(aValue);
}
bool SessionImpl::isAutoCommit(const std::string&) const
{
return _sessionHandle.isAutoCommit();
}
void SessionImpl::setAsynchronousCommit(const std::string&, bool aValue)
{
_sessionHandle.setAsynchronousCommit(aValue);
}
bool SessionImpl::isAsynchronousCommit(const std::string&) const
{
return _sessionHandle.isAsynchronousCommit();
}
void SessionImpl::setTransactionIsolation(Poco::UInt32 aTI)
{
return _sessionHandle.setTransactionIsolation(aTI);
}
Poco::UInt32 SessionImpl::getTransactionIsolation() const
{
return _sessionHandle.transactionIsolation();
}
bool SessionImpl::hasTransactionIsolation(Poco::UInt32 aTI) const
{
return _sessionHandle.hasTransactionIsolation(aTI);
}
void SessionImpl::setBinaryExtraction(const std::string& feature, bool enabled)
{
if (enabled && _sessionHandle.parameterStatus("integer_datetimes") != "on")
throw PostgreSQLException("binary extraction is not supported with this server (ingeger_datetimes must be enabled on the server)");
_binaryExtraction = enabled;
}
} } } // namespace Poco::Data::PostgreSQL