mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 16:57:16 +01:00
4a6bfc086c
Switched to POCO library for unified platform/library interface. Deprecated the external module API. It was creating more problems than solving. Removed most built-in libraries in favor of system libraries for easier maintenance. Cleaned and secured code with help from static analyzers.
320 lines
6.3 KiB
C++
320 lines
6.3 KiB
C++
//
|
|
// Statement.cpp
|
|
//
|
|
// Library: Data
|
|
// Package: DataCore
|
|
// Module: Statement
|
|
//
|
|
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
|
// and Contributors.
|
|
//
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
|
|
|
|
#include "Poco/Data/Statement.h"
|
|
#include "Poco/Data/DataException.h"
|
|
#include "Poco/Data/Extraction.h"
|
|
#include "Poco/Data/Session.h"
|
|
#include "Poco/Data/Bulk.h"
|
|
#include "Poco/Any.h"
|
|
#include "Poco/Tuple.h"
|
|
#include "Poco/ActiveMethod.h"
|
|
#include <algorithm>
|
|
|
|
|
|
namespace Poco {
|
|
namespace Data {
|
|
|
|
|
|
Statement::Statement(StatementImpl::Ptr pImpl):
|
|
_pImpl(pImpl),
|
|
_async(false)
|
|
{
|
|
poco_check_ptr (pImpl);
|
|
}
|
|
|
|
|
|
Statement::Statement(Session& session):
|
|
_async(false)
|
|
{
|
|
reset(session);
|
|
}
|
|
|
|
|
|
Statement::Statement(const Statement& stmt):
|
|
_pImpl(stmt._pImpl),
|
|
_async(stmt._async),
|
|
_pResult(stmt._pResult),
|
|
_pAsyncExec(stmt._pAsyncExec),
|
|
_arguments(stmt._arguments),
|
|
_pRowFormatter(stmt._pRowFormatter)
|
|
{
|
|
}
|
|
|
|
|
|
Statement::Statement(Statement&& stmt) noexcept:
|
|
_pImpl(std::move(stmt._pImpl)),
|
|
_async(std::move(stmt._async)),
|
|
_pResult(std::move(stmt._pResult)),
|
|
_pAsyncExec(std::move(stmt._pAsyncExec)),
|
|
_arguments(std::move(stmt._arguments)),
|
|
_pRowFormatter(std::move(stmt._pRowFormatter))
|
|
{
|
|
}
|
|
|
|
|
|
Statement::~Statement()
|
|
{
|
|
}
|
|
|
|
|
|
Statement& Statement::operator = (const Statement& stmt)
|
|
{
|
|
Statement tmp(stmt);
|
|
swap(tmp);
|
|
return *this;
|
|
}
|
|
|
|
|
|
Statement& Statement::operator = (Statement&& stmt) noexcept
|
|
{
|
|
_pImpl = std::move(stmt._pImpl);
|
|
_async = std::move(stmt._async);
|
|
_pResult = std::move(stmt._pResult);
|
|
_pAsyncExec = std::move(stmt._pAsyncExec);
|
|
_arguments = std::move(stmt._arguments);
|
|
_pRowFormatter = std::move(stmt._pRowFormatter);
|
|
|
|
return *this;
|
|
}
|
|
|
|
void Statement::swap(Statement& other)
|
|
{
|
|
using std::swap;
|
|
|
|
swap(_pImpl, other._pImpl);
|
|
swap(_async, other._async);
|
|
swap(_pAsyncExec, other._pAsyncExec);
|
|
swap(_pResult, other._pResult);
|
|
_arguments.swap(other._arguments);
|
|
swap(_pRowFormatter, other._pRowFormatter);
|
|
}
|
|
|
|
|
|
Statement& Statement::reset(Session& session)
|
|
{
|
|
Statement stmt(session.createStatementImpl());
|
|
swap(stmt);
|
|
return *this;
|
|
}
|
|
|
|
|
|
std::size_t Statement::execute(bool reset)
|
|
{
|
|
Mutex::ScopedLock lock(_mutex);
|
|
bool isDone = done();
|
|
if (initialized() || paused() || isDone)
|
|
{
|
|
if (_arguments.size())
|
|
{
|
|
_pImpl->formatSQL(_arguments);
|
|
_arguments.clear();
|
|
}
|
|
|
|
if (!isAsync())
|
|
{
|
|
if (isDone) _pImpl->reset();
|
|
return _pImpl->execute(reset);
|
|
}
|
|
else
|
|
{
|
|
doAsyncExec();
|
|
return 0;
|
|
}
|
|
}
|
|
else throw InvalidAccessException("Statement still executing.");
|
|
}
|
|
|
|
|
|
const Statement::Result& Statement::executeAsync(bool reset)
|
|
{
|
|
Mutex::ScopedLock lock(_mutex);
|
|
if (initialized() || paused() || done())
|
|
return doAsyncExec(reset);
|
|
else
|
|
throw InvalidAccessException("Statement still executing.");
|
|
}
|
|
|
|
|
|
const Statement::Result& Statement::doAsyncExec(bool reset)
|
|
{
|
|
if (done()) _pImpl->reset();
|
|
if (!_pAsyncExec)
|
|
_pAsyncExec = new AsyncExecMethod(_pImpl, &StatementImpl::execute);
|
|
_pResult = new Result((*_pAsyncExec)(reset));
|
|
return *_pResult;
|
|
}
|
|
|
|
|
|
void Statement::setAsync(bool async)
|
|
{
|
|
_async = async;
|
|
if (_async && !_pAsyncExec)
|
|
_pAsyncExec = new AsyncExecMethod(_pImpl, &StatementImpl::execute);
|
|
}
|
|
|
|
|
|
std::size_t Statement::wait(long milliseconds)
|
|
{
|
|
if (!_pResult) return 0;
|
|
bool success = true;
|
|
if (WAIT_FOREVER != milliseconds)
|
|
success = _pResult->tryWait(milliseconds);
|
|
else
|
|
_pResult->wait();
|
|
|
|
if (_pResult->exception())
|
|
throw *_pResult->exception();
|
|
else if (!success)
|
|
throw TimeoutException("Statement timed out.");
|
|
|
|
return _pResult->data();
|
|
}
|
|
|
|
|
|
const std::string& Statement::getStorage() const
|
|
{
|
|
switch (storage())
|
|
{
|
|
case STORAGE_VECTOR:
|
|
return StatementImpl::VECTOR;
|
|
case STORAGE_LIST:
|
|
return StatementImpl::LIST;
|
|
case STORAGE_DEQUE:
|
|
return StatementImpl::DEQUE;
|
|
case STORAGE_UNKNOWN:
|
|
return StatementImpl::UNKNOWN;
|
|
}
|
|
|
|
throw IllegalStateException("Invalid storage setting.");
|
|
}
|
|
|
|
|
|
Statement& Statement::operator , (Manipulator manip)
|
|
{
|
|
manip(*this);
|
|
return *this;
|
|
}
|
|
|
|
|
|
Statement& Statement::addBind(AbstractBinding::Ptr pBind)
|
|
{
|
|
if (pBind->isBulk())
|
|
{
|
|
if (!_pImpl->isBulkSupported())
|
|
throw InvalidAccessException("Bulk not supported by this session.");
|
|
|
|
if(_pImpl->bulkBindingAllowed())
|
|
_pImpl->setBulkBinding();
|
|
else
|
|
throw InvalidAccessException("Bulk and non-bulk binding modes can not be mixed.");
|
|
}
|
|
else _pImpl->forbidBulk();
|
|
|
|
_pImpl->addBind(pBind);
|
|
return *this;
|
|
}
|
|
|
|
|
|
Statement& Statement::addExtract(AbstractExtraction::Ptr pExtract)
|
|
{
|
|
if (pExtract->isBulk())
|
|
{
|
|
if (!_pImpl->isBulkSupported())
|
|
throw InvalidAccessException("Bulk not supported by this session.");
|
|
|
|
if(_pImpl->bulkExtractionAllowed())
|
|
{
|
|
Bulk b(pExtract->getLimit());
|
|
_pImpl->setBulkExtraction(b);
|
|
}
|
|
else
|
|
throw InvalidAccessException("Bulk and non-bulk extraction modes can not be mixed.");
|
|
}
|
|
else _pImpl->forbidBulk();
|
|
|
|
_pImpl->addExtract(pExtract);
|
|
return *this;
|
|
}
|
|
|
|
|
|
Statement& Statement::operator , (const Limit& extrLimit)
|
|
{
|
|
if (_pImpl->isBulkExtraction() && _pImpl->extractionLimit() != extrLimit)
|
|
throw InvalidArgumentException("Limit for bulk extraction already set.");
|
|
|
|
_pImpl->setExtractionLimit(extrLimit);
|
|
return *this;
|
|
}
|
|
|
|
|
|
Statement& Statement::operator , (const Range& extrRange)
|
|
{
|
|
if (_pImpl->isBulkExtraction())
|
|
throw InvalidAccessException("Can not set range for bulk extraction.");
|
|
|
|
_pImpl->setExtractionLimit(extrRange.lower());
|
|
_pImpl->setExtractionLimit(extrRange.upper());
|
|
return *this;
|
|
}
|
|
|
|
|
|
Statement& Statement::operator , (const Bulk& bulk)
|
|
{
|
|
if (!_pImpl->isBulkSupported())
|
|
throw InvalidAccessException("Bulk not supported by this session.");
|
|
|
|
if (0 == _pImpl->extractions().size() &&
|
|
0 == _pImpl->bindings().size() &&
|
|
_pImpl->bulkExtractionAllowed() &&
|
|
_pImpl->bulkBindingAllowed())
|
|
{
|
|
_pImpl->setBulkExtraction(bulk);
|
|
_pImpl->setBulkBinding();
|
|
}
|
|
else
|
|
throw InvalidAccessException("Can not set bulk operations.");
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
Statement& Statement::operator , (BulkFnType)
|
|
{
|
|
const Limit& limit(_pImpl->extractionLimit());
|
|
if (limit.isHardLimit() ||
|
|
limit.isLowerLimit() ||
|
|
Limit::LIMIT_UNLIMITED == limit.value())
|
|
{
|
|
throw InvalidAccessException("Bulk is only allowed with limited extraction,"
|
|
"non-hard and zero-based limits.");
|
|
}
|
|
|
|
Bulk bulk(limit);
|
|
_pImpl->setBulkExtraction(bulk);
|
|
_pImpl->setBulkBinding();
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
Session Statement::session()
|
|
{
|
|
Poco::AutoPtr<SessionImpl> ps(&impl()->session(), true);
|
|
return Session(ps);
|
|
}
|
|
|
|
|
|
} } // namespace Poco::Data
|