[Received via email]
[...]
The problem is that the Statement object cannot be used again after it throws. For example it throws when performing some operations on locked table etc.
The Statement object remains in ST_BOUND state and literally speaking the object is useless, and we cannot invoke execute on it once again.
We use it like this: (see below) -> the lambda is used to recreate the Statement object in case it throws:
auto select = [&session, &sql, &keyCopy, &metadata, &data] () -> Poco::Data::Statement {
Statement select (session);
select << sql, use(keyCopy, "key"), into(metadata), into(data);
return select;
};
if (executeTempFailureRetry(m_logger, m_name, select) == 0)
{
throw StorageEmptyException("No records for key \"" + key + "\"");
}
…
typedef std::function<Poco::Data::Statement()> StatementCreator;
std::size_t SqliteStorage::executeTempFailureRetry(Poco::Logger &logger,
const std::string &name,
StatementCreator statementCreator)
{
int exec = 0;
while (true)
{
try
{
++exec;
return statementCreator().execute();
}
catch (const Poco::Data::SQLite::DBLockedException &ex)
{
logger.warning("Could not temporarily (%d) access database table \"%s\": %s",
exec, name, ex.message());
continue;
}
catch (const Poco::Data::SQLite::TableLockedException &ex)
{
logger.warning("Could not temporarily (%d) access database table \"%s\": %s",
exec, name, ex.message());
continue;
}
catch (const Poco::Data::DataException &ex)
{
throw Storage::StorageErrorException(ex.message());
}
}
}
[Received via email]
[...]
The problem is that the Statement object cannot be used again after it throws. For example it throws when performing some operations on locked table etc.
The Statement object remains in ST_BOUND state and literally speaking the object is useless, and we cannot invoke execute on it once again.
We use it like this: (see below) -> the lambda is used to recreate the Statement object in case it throws: