// // 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 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 ps(&impl()->session(), true); return Session(ps); } } } // namespace Poco::Data