improve BLOB handling, clean-up code

This commit is contained in:
Günter Obiltschnig
2021-06-25 09:22:58 +02:00
parent 52e0581edc
commit ca3d168153
11 changed files with 101 additions and 145 deletions

View File

@@ -205,8 +205,8 @@ Binder::bindVector() const
void Binder::updateBindVectorToCurrentValues()
{
InputParameterVector::iterator itr = _bindVector.begin();
InputParameterVector::iterator itrEnd = _bindVector.end();
InputParameterVector::iterator itr = _bindVector.begin();
InputParameterVector::iterator itrEnd = _bindVector.end();
for (; itr != itrEnd; ++itr)
{

View File

@@ -17,6 +17,8 @@
#include "Poco/Data/Time.h"
#include "Poco/NumberParser.h"
#include "Poco/DateTimeParser.h"
#include "Poco/MemoryStream.h"
#include "Poco/HexBinaryDecoder.h"
#include <limits>
@@ -42,14 +44,10 @@ bool Extractor::extract(std::size_t pos, Poco::Int8& val)
OutputParameter outputParameter = extractPreamble(pos);
int tempVal = 0;
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParse(outputParameter.pData(), tempVal)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParse(outputParameter.pData(), tempVal))
{
return false;
}
val = static_cast<Int8>(tempVal);
return true;
@@ -61,14 +59,10 @@ bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
OutputParameter outputParameter = extractPreamble(pos);
unsigned int tempVal = 0;
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParseUnsigned(outputParameter.pData(), tempVal)
)
if (isColumnNull(outputParameter)|| !Poco::NumberParser::tryParseUnsigned(outputParameter.pData(), tempVal))
{
return false;
}
val = static_cast<UInt8>(tempVal);
return true;
@@ -80,14 +74,10 @@ bool Extractor::extract(std::size_t pos, Poco::Int16& val)
OutputParameter outputParameter = extractPreamble(pos);
int tempVal = 0;
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParse(outputParameter.pData(), tempVal)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParse(outputParameter.pData(), tempVal))
{
return false;
}
val = static_cast<Int16>(tempVal);
return true;
@@ -99,14 +89,10 @@ bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
OutputParameter outputParameter = extractPreamble(pos);
unsigned int tempVal = 0;
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParseUnsigned(outputParameter.pData(), tempVal)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParseUnsigned(outputParameter.pData(), tempVal))
{
return false;
}
val = static_cast<UInt16>(tempVal);
return true;
@@ -117,9 +103,7 @@ bool Extractor::extract(std::size_t pos, Poco::Int32& val)
{
OutputParameter outputParameter = extractPreamble(pos);
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParse(outputParameter.pData(), val)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParse(outputParameter.pData(), val))
{
return false;
}
@@ -132,9 +116,7 @@ bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
{
OutputParameter outputParameter = extractPreamble(pos);
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParseUnsigned(outputParameter.pData(), val)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParseUnsigned(outputParameter.pData(), val))
{
return false;
}
@@ -147,9 +129,7 @@ bool Extractor::extract(std::size_t pos, Poco::Int64& val)
{
OutputParameter outputParameter = extractPreamble(pos);
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParse64(outputParameter.pData(), val)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParse64(outputParameter.pData(), val))
{
return false;
}
@@ -162,9 +142,7 @@ bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
{
OutputParameter outputParameter = extractPreamble(pos);
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParseUnsigned64(outputParameter.pData(), val)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParseUnsigned64(outputParameter.pData(), val))
{
return false;
}
@@ -179,13 +157,10 @@ bool Extractor::extract(std::size_t pos, long& val)
OutputParameter outputParameter = extractPreamble(pos);
Poco::Int64 tempVal = 0;
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParse64(outputParameter.pData(), tempVal)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParse64(outputParameter.pData(), tempVal))
{
return false;
}
val = (long)tempVal;
return true;
@@ -197,14 +172,10 @@ bool Extractor::extract(std::size_t pos, unsigned long& val)
OutputParameter outputParameter = extractPreamble(pos);
Poco::UInt64 tempVal = 0;
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParseUnsigned64(outputParameter.pData(), tempVal)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParseUnsigned64(outputParameter.pData(), tempVal))
{
return false;
}
val = (unsigned long)tempVal;
return true;
@@ -216,19 +187,12 @@ bool Extractor::extract(std::size_t pos, bool& val)
{
OutputParameter outputParameter = extractPreamble(pos);
if ( isColumnNull(outputParameter))
if (isColumnNull(outputParameter))
{
return false;
}
if ('t' == *outputParameter.pData())
{
val = true;
}
else
{
val = false;
}
val = 't' == *outputParameter.pData();
return true;
}
@@ -239,15 +203,11 @@ bool Extractor::extract(std::size_t pos, float& val)
OutputParameter outputParameter = extractPreamble(pos);
double tempVal = 0.0;
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParseFloat(outputParameter.pData(), tempVal)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParseFloat(outputParameter.pData(), tempVal))
{
return false;
}
val = (float)tempVal;
val = static_cast<float>(tempVal);
return true;
}
@@ -257,9 +217,7 @@ bool Extractor::extract(std::size_t pos, double& val)
{
OutputParameter outputParameter = extractPreamble(pos);
if ( isColumnNull(outputParameter)
|| ! Poco::NumberParser::tryParseFloat(outputParameter.pData(), val)
)
if (isColumnNull(outputParameter) || !Poco::NumberParser::tryParseFloat(outputParameter.pData(), val))
{
return false;
}
@@ -272,11 +230,10 @@ bool Extractor::extract(std::size_t pos, char& val)
{
OutputParameter outputParameter = extractPreamble(pos);
if (isColumnNull(outputParameter))
if (isColumnNull(outputParameter))
{
return false;
}
val = *outputParameter.pData();
return true;
@@ -291,7 +248,6 @@ bool Extractor::extract(std::size_t pos, std::string& val)
{
return false;
}
val.assign(outputParameter.pData(), outputParameter.size());
return true;
@@ -309,32 +265,24 @@ bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
// convert the PostgreSQL text format to binary and append to the BLOB
// Format: \x10843029479abcf ... two characters for every byte
//
// The code below can be made more efficient by converting more than one byte at a time
// also if BLOB had a resize method it would be useful to allocate memory in one
// attempt.
//
const char * pBLOB = reinterpret_cast<const char*>(outputParameter.pData());
std::size_t blobSize = outputParameter.size();
val = Poco::Data::BLOB(); // don't share contents with _default
if ( '\\' == pBLOB[0]
&& 'x' == pBLOB[1] // preamble to BYTEA data format in text form is \x
)
if (blobSize > 2 && '\\' == pBLOB[0] && 'x' == pBLOB[1]) // preamble to BYTEA data format in text form is \x
{
blobSize -= 2; // lose the preamble
blobSize /= 2; // each byte is encoded as two text characters
for (int i = 0; i < blobSize * 2; i += 2)
Poco::MemoryInputStream mistr(pBLOB + 2, blobSize);
Poco::HexBinaryDecoder decoder(mistr);
auto* pDecoderBuf = decoder.rdbuf();
blobSize /= 2;
val.resize(blobSize);
char* pData = reinterpret_cast<char*>(val.rawContent());
while (blobSize-- > 0)
{
std::string buffer(&pBLOB[i + 2], 2);
unsigned int binaryBuffer = 0;
if (Poco::NumberParser::tryParseHex(buffer, binaryBuffer))
{
UInt8 finalBinaryBuffer = static_cast<UInt8>(binaryBuffer); // downsize
val.appendRaw(&finalBinaryBuffer, 1);
}
*pData++ = pDecoderBuf->sbumpc();
}
}
return true;
@@ -349,7 +297,6 @@ bool Extractor::extract(std::size_t pos, Poco::Data::CLOB& val)
{
return false;
}
val.assignRaw(outputParameter.pData(), outputParameter.size());
return true;
@@ -367,14 +314,11 @@ bool Extractor::extract(std::size_t pos, DateTime& val)
int tzd = -1;
DateTime dateTime;
if (! DateTimeParser::tryParse(outputParameter.pData(), dateTime, tzd))
if (!DateTimeParser::tryParse(outputParameter.pData(), dateTime, tzd))
{
return false;
}
dateTime.makeUTC(tzd);
val = dateTime;
return true;
@@ -389,17 +333,13 @@ bool Extractor::extract(std::size_t pos, Date& val)
{
return false;
}
int tzd = -1;
DateTime dateTime;
if (! DateTimeParser::tryParse(outputParameter.pData(), dateTime, tzd))
if (!DateTimeParser::tryParse(outputParameter.pData(), dateTime, tzd))
{
return false;
}
dateTime.makeUTC(tzd);
val.assign(dateTime.year(), dateTime.month(), dateTime.day());
return true;
@@ -414,10 +354,8 @@ bool Extractor::extract(std::size_t pos, Time& val)
{
return false;
}
int tzd = -1;
DateTime dateTime;
if (! DateTimeParser::tryParse("%H:%M:%s%z", outputParameter.pData(), dateTime, tzd))
{
return false;

View File

@@ -108,8 +108,7 @@ bool PostgreSQLStatementImpl::canBind() const
{
bool ret = false;
if ((_statementExecutor.state() >= StatementExecutor::STMT_COMPILED)
&& !bindings().empty())
if ((_statementExecutor.state() >= StatementExecutor::STMT_COMPILED) && !bindings().empty())
{
ret = (*bindings().begin())->canBind();
}

View File

@@ -86,7 +86,7 @@ void SessionHandle::connect(const std::string& aConnectionString)
_pConnection = PQconnectdb(aConnectionString.c_str());
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw ConnectionFailedException(std::string("Connection Error: ") + lastErrorNoLock());
}
@@ -151,6 +151,7 @@ void SessionHandle::disconnect()
}
}
// TODO: Figure out what happens if a connection is reset with a pending transaction
bool SessionHandle::reset()
{
@@ -174,7 +175,7 @@ std::string SessionHandle::lastError() const
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
return std::string();
}
@@ -196,7 +197,7 @@ void SessionHandle::startTransaction()
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -223,7 +224,7 @@ void SessionHandle::commit()
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -247,7 +248,7 @@ void SessionHandle::rollback()
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -291,7 +292,7 @@ void SessionHandle::setAsynchronousCommit(bool aShouldAsynchronousCommit)
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -318,7 +319,7 @@ void SessionHandle::cancel()
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -335,7 +336,7 @@ void SessionHandle::setTransactionIsolation(Poco::UInt32 aTI)
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -345,7 +346,7 @@ void SessionHandle::setTransactionIsolation(Poco::UInt32 aTI)
return;
}
if (! hasTransactionIsolation(aTI))
if (!hasTransactionIsolation(aTI))
{
throw Poco::InvalidArgumentException("setTransactionIsolation()");
}
@@ -354,12 +355,12 @@ void SessionHandle::setTransactionIsolation(Poco::UInt32 aTI)
switch (aTI)
{
case Session::TRANSACTION_READ_COMMITTED:
isolationLevel = POSTGRESQL_READ_COMMITTED; break;
case Session::TRANSACTION_REPEATABLE_READ:
isolationLevel = POSTGRESQL_REPEATABLE_READ; break;
case Session::TRANSACTION_SERIALIZABLE:
isolationLevel = POSTGRESQL_SERIALIZABLE; break;
case Session::TRANSACTION_READ_COMMITTED:
isolationLevel = POSTGRESQL_READ_COMMITTED; break;
case Session::TRANSACTION_REPEATABLE_READ:
isolationLevel = POSTGRESQL_REPEATABLE_READ; break;
case Session::TRANSACTION_SERIALIZABLE:
isolationLevel = POSTGRESQL_SERIALIZABLE; break;
}
PGresult* pPQResult = PQexec(_pConnection, Poco::format("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL %s", isolationLevel).c_str());
@@ -393,12 +394,12 @@ void SessionHandle::deallocatePreparedStatement(const std::string& aPreparedStat
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
if (! _inTransaction)
if (!_inTransaction)
{
deallocatePreparedStatementNoLock(aPreparedStatementToDeAllocate);
}
@@ -431,7 +432,7 @@ void SessionHandle::deallocatePreparedStatementNoLock(const std::string& aPrepar
void SessionHandle::deallocateStoredPreparedStatements()
{
// DO NOT ACQUIRE THE MUTEX IN PRIVATE METHODS
while (! _preparedStatementsToBeDeallocated.empty())
while (!_preparedStatementsToBeDeallocated.empty())
{
deallocatePreparedStatementNoLock(_preparedStatementsToBeDeallocated.back());
@@ -444,7 +445,7 @@ int SessionHandle::serverVersion() const
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -457,7 +458,7 @@ int SessionHandle::serverProcessID() const
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -470,7 +471,7 @@ int SessionHandle::protocoVersion() const
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -483,7 +484,7 @@ std::string SessionHandle::clientEncoding() const
{
Poco::FastMutex::ScopedLock mutexLocker(_sessionMutex);
if (! isConnectedNoLock())
if (!isConnectedNoLock())
{
throw NotConnectedException();
}
@@ -502,7 +503,7 @@ SessionParametersMap SessionHandle::setConnectionInfoParameters(PQconninfoOption
{
SessionParametersMap sessionParametersMap;
while (0 != pConnInfOpt->keyword)
while (pConnInfOpt->keyword)
{
try
{
@@ -542,7 +543,7 @@ SessionParametersMap SessionHandle::connectionDefaultParameters()
SessionParametersMap SessionHandle::connectionParameters() const
{
if (! isConnected())
if (!isConnected())
{
throw NotConnectedException();
}

View File

@@ -38,7 +38,7 @@ namespace
{
std::string connectionString;
for (std::map<std::string, std::string>::const_iterator citr = anOptionsMap.begin(); citr != anOptionsMap.end(); ++citr)
for (auto citr = anOptionsMap.begin(); citr != anOptionsMap.end(); ++citr)
{
connectionString.append(citr->first);
connectionString.append("=");
@@ -93,7 +93,7 @@ void SessionImpl::open(const std::string& aConnectionString)
throw ConnectionException("Session already connected");
}
if (! aConnectionString.empty())
if (!aConnectionString.empty())
{
setConnectionString(aConnectionString);
}

View File

@@ -46,7 +46,6 @@ namespace
Poco::RegularExpression::Match match = { 0 , 0 }; // Match is a struct, not a class :-(
std::size_t startingPosition = 0;
while (match.offset != std::string::npos)
{
try
@@ -110,7 +109,7 @@ StatementExecutor::State StatementExecutor::state() const
void StatementExecutor::prepare(const std::string& aSQLStatement)
{
if (! _sessionHandle.isConnected()) throw NotConnectedException();
if (!_sessionHandle.isConnected()) throw NotConnectedException();
if (_state >= STMT_COMPILED) return;
// clear out the metadata. One way or another it is now obsolete.
@@ -160,7 +159,7 @@ void StatementExecutor::prepare(const std::string& aSQLStatement)
{
PQResultClear resultClearer(ptrPGResult);
if (! ptrPGResult || PQresultStatus(ptrPGResult) != PGRES_COMMAND_OK)
if (!ptrPGResult || PQresultStatus(ptrPGResult) != PGRES_COMMAND_OK)
{
throw StatementException(std::string("postgresql_stmt_describe error: ") +
PQresultErrorMessage (ptrPGResult) + " " + aSQLStatement);
@@ -186,7 +185,7 @@ void StatementExecutor::prepare(const std::string& aSQLStatement)
void StatementExecutor::bindParams(const InputParameterVector& anInputParameterVector)
{
if (! _sessionHandle.isConnected()) throw NotConnectedException();
if (!_sessionHandle.isConnected()) throw NotConnectedException();
if (_state < STMT_COMPILED) throw StatementException("Statement is not compiled yet");
@@ -203,7 +202,7 @@ void StatementExecutor::bindParams(const InputParameterVector& anInputParameterV
void StatementExecutor::execute()
{
if (! _sessionHandle.isConnected()) throw NotConnectedException();
if (!_sessionHandle.isConnected()) throw NotConnectedException();
if (_state < STMT_COMPILED) throw StatementException("Statement is not compiled yet");
@@ -225,8 +224,8 @@ void StatementExecutor::execute()
std::vector<int> parameterLengthVector;
std::vector<int> parameterFormatVector;
InputParameterVector::const_iterator cItr = _inputParameterVector.begin();
InputParameterVector::const_iterator cItrEnd = _inputParameterVector.end();
InputParameterVector::const_iterator cItr = _inputParameterVector.begin();
InputParameterVector::const_iterator cItrEnd = _inputParameterVector.end();
for (; cItr != cItrEnd; ++cItr)
{
@@ -315,7 +314,7 @@ void StatementExecutor::execute()
bool StatementExecutor::fetch()
{
if (! _sessionHandle.isConnected())
if (!_sessionHandle.isConnected())
{
throw NotConnectedException();
}

View File

@@ -27,13 +27,9 @@ namespace PostgreSQL {
std::string Utility::serverInfo(SessionHandle* aHandlePtr)
{
std::string srvrInfo = "Process ID: ";
srvrInfo.append(Poco::NumberFormatter::format(aHandlePtr->serverProcessID()));
srvrInfo.append(" Protocol Version: ");
srvrInfo.append(Poco::NumberFormatter::format(aHandlePtr->protocoVersion()));
return srvrInfo;
}
@@ -61,7 +57,6 @@ std::string Utility::hostInfo(SessionHandle* aHandlePtr)
SessionParametersMap parametersMap = aHandlePtr->connectionParameters();
SessionParametersMap::const_iterator cItr = parametersMap.find("host");
if (parametersMap.end() == cItr)
{
return std::string();