mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-09-16 09:17:17 +02:00
Major plugin refactor and cleanup.
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.
This commit is contained in:
127
vendor/POCO/Data/SQLite/src/Binder.cpp
vendored
Normal file
127
vendor/POCO/Data/SQLite/src/Binder.cpp
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// Binder.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: Binder
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Binder.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/DateTimeFormat.h"
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
using Poco::DateTimeFormatter;
|
||||
using Poco::DateTimeFormat;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
Binder::Binder(sqlite3_stmt* pStmt):
|
||||
_pStmt(pStmt)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Binder::~Binder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Poco::Int32 &val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_int(_pStmt, (int) pos, val);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_int64(_pStmt, (int) pos, val);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_INT64_IS_LONG
|
||||
void Binder::bind(std::size_t pos, const long &val, Direction dir)
|
||||
{
|
||||
long tmp = static_cast<long>(val);
|
||||
int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
void Binder::bind(std::size_t pos, const unsigned long &val, Direction dir)
|
||||
{
|
||||
long tmp = static_cast<long>(val);
|
||||
int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp);
|
||||
checkReturn(rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const double &val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_double(_pStmt, (int) pos, val);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_text(_pStmt, (int) pos, val.c_str(), (int) val.size()*sizeof(char), SQLITE_TRANSIENT);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Date& val, Direction dir)
|
||||
{
|
||||
DateTime dt(val.year(), val.month(), val.day());
|
||||
std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_DATE_FORMAT));
|
||||
bind(pos, str, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Time& val, Direction dir)
|
||||
{
|
||||
DateTime dt;
|
||||
dt.assign(dt.year(), dt.month(), dt.day(), val.hour(), val.minute(), val.second());
|
||||
std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_TIME_FORMAT));
|
||||
bind(pos, str, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
|
||||
{
|
||||
std::string dt(DateTimeFormatter::format(val, DateTimeFormat::ISO8601_FORMAT));
|
||||
bind(pos, dt, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const NullData&, Direction)
|
||||
{
|
||||
sqlite3_bind_null(_pStmt, static_cast<int>(pos));
|
||||
}
|
||||
|
||||
|
||||
void Binder::checkReturn(int rc)
|
||||
{
|
||||
if (rc != SQLITE_OK)
|
||||
Utility::throwException(sqlite3_db_handle(_pStmt), rc);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
74
vendor/POCO/Data/SQLite/src/Connector.cpp
vendored
Normal file
74
vendor/POCO/Data/SQLite/src/Connector.cpp
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Connector.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: Connector
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Connector.h"
|
||||
#include "Poco/Data/SQLite/SessionImpl.h"
|
||||
#include "Poco/Data/SessionFactory.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const std::string Connector::KEY("sqlite");
|
||||
|
||||
|
||||
Connector::Connector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Connector::~Connector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
|
||||
std::size_t timeout)
|
||||
{
|
||||
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
|
||||
}
|
||||
|
||||
|
||||
void Connector::registerConnector()
|
||||
{
|
||||
Poco::Data::SessionFactory::instance().add(new Connector());
|
||||
}
|
||||
|
||||
|
||||
void Connector::unregisterConnector()
|
||||
{
|
||||
Poco::Data::SessionFactory::instance().remove(KEY);
|
||||
}
|
||||
|
||||
|
||||
void Connector::enableSharedCache(bool flag)
|
||||
{
|
||||
sqlite3_enable_shared_cache(flag ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
void Connector::enableSoftHeapLimit(int limit)
|
||||
{
|
||||
sqlite3_soft_heap_limit(limit);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
238
vendor/POCO/Data/SQLite/src/Extractor.cpp
vendored
Normal file
238
vendor/POCO/Data/SQLite/src/Extractor.cpp
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
//
|
||||
// Extractor.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: Extractor
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Extractor.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#include "Poco/DateTimeParser.h"
|
||||
#include "Poco/Exception.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
using Poco::DateTimeParser;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
Extractor::Extractor(sqlite3_stmt* pStmt):
|
||||
_pStmt(pStmt)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Extractor::~Extractor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int32& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int64& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int64(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_INT64_IS_LONG
|
||||
bool Extractor::extract(std::size_t pos, long& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, unsigned long& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, double& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_double(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, std::string& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
const char *pBuf = reinterpret_cast<const char*>(sqlite3_column_text(_pStmt, (int) pos));
|
||||
if (!pBuf)
|
||||
val.clear();
|
||||
else
|
||||
val.assign(pBuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int8& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int16& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int64(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, bool& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = (0 != sqlite3_column_int(_pStmt, (int) pos));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, float& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = static_cast<float>(sqlite3_column_double(_pStmt, (int) pos));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, char& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Date& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
std::string str;
|
||||
extract(pos, str);
|
||||
int tzd;
|
||||
DateTime dt = DateTimeParser::parse(Utility::SQLITE_DATE_FORMAT, str, tzd);
|
||||
val = dt;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Time& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
std::string str;
|
||||
extract(pos, str);
|
||||
int tzd;
|
||||
DateTime dt = DateTimeParser::parse(Utility::SQLITE_TIME_FORMAT, str, tzd);
|
||||
val = dt;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, DateTime& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
std::string dt;
|
||||
extract(pos, dt);
|
||||
int tzd;
|
||||
DateTimeParser::parse(dt, val, tzd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Any& val)
|
||||
{
|
||||
return extractImpl(pos, val);
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val)
|
||||
{
|
||||
return extractImpl(pos, val);
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::isNull(std::size_t pos, std::size_t)
|
||||
{
|
||||
if (pos >= _nulls.size())
|
||||
_nulls.resize(pos + 1);
|
||||
|
||||
if (!_nulls[pos].first)
|
||||
{
|
||||
_nulls[pos].first = true;
|
||||
_nulls[pos].second = (SQLITE_NULL == sqlite3_column_type(_pStmt, static_cast<int>(pos)));
|
||||
}
|
||||
|
||||
return _nulls[pos].second;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
203
vendor/POCO/Data/SQLite/src/Notifier.cpp
vendored
Normal file
203
vendor/POCO/Data/SQLite/src/Notifier.cpp
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// Notifier.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: Notifier
|
||||
//
|
||||
// Implementation of Notifier
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Notifier.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
Notifier::Notifier(const Session& session, EnabledEventType enabled):
|
||||
_session(session)
|
||||
{
|
||||
if (enabled & SQLITE_NOTIFY_UPDATE) enableUpdate();
|
||||
if (enabled & SQLITE_NOTIFY_COMMIT) enableCommit();
|
||||
if (enabled & SQLITE_NOTIFY_ROLLBACK) enableRollback();
|
||||
}
|
||||
|
||||
|
||||
Notifier::Notifier(const Session& session, const Any& value, EnabledEventType enabled):
|
||||
_session(session),
|
||||
_value(value)
|
||||
{
|
||||
if (enabled & SQLITE_NOTIFY_UPDATE) enableUpdate();
|
||||
if (enabled & SQLITE_NOTIFY_COMMIT) enableCommit();
|
||||
if (enabled & SQLITE_NOTIFY_ROLLBACK) enableRollback();
|
||||
}
|
||||
|
||||
|
||||
Notifier::~Notifier()
|
||||
{
|
||||
try
|
||||
{
|
||||
disableAll();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableUpdate()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), &sqliteUpdateCallbackFn, this))
|
||||
_enabledEvents |= SQLITE_NOTIFY_UPDATE;
|
||||
|
||||
return updateEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableUpdate()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), (Utility::UpdateCallbackType) 0, this))
|
||||
_enabledEvents &= ~SQLITE_NOTIFY_UPDATE;
|
||||
|
||||
return !updateEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::updateEnabled() const
|
||||
{
|
||||
return 0 != (_enabledEvents & SQLITE_NOTIFY_UPDATE);
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableCommit()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), &sqliteCommitCallbackFn, this))
|
||||
_enabledEvents |= SQLITE_NOTIFY_COMMIT;
|
||||
|
||||
return commitEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableCommit()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), (Utility::CommitCallbackType) 0, this))
|
||||
_enabledEvents &= ~SQLITE_NOTIFY_COMMIT;
|
||||
|
||||
return !commitEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::commitEnabled() const
|
||||
{
|
||||
return 0 != (_enabledEvents & SQLITE_NOTIFY_COMMIT);
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableRollback()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), &sqliteRollbackCallbackFn, this))
|
||||
_enabledEvents |= SQLITE_NOTIFY_ROLLBACK;
|
||||
|
||||
return rollbackEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableRollback()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), (Utility::RollbackCallbackType) 0, this))
|
||||
_enabledEvents &= ~SQLITE_NOTIFY_ROLLBACK;
|
||||
|
||||
return !rollbackEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::rollbackEnabled() const
|
||||
{
|
||||
return 0 != (_enabledEvents & SQLITE_NOTIFY_ROLLBACK);
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableAll()
|
||||
{
|
||||
return enableUpdate() && enableCommit() && enableRollback();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableAll()
|
||||
{
|
||||
return disableUpdate() && disableCommit() && disableRollback();
|
||||
}
|
||||
|
||||
|
||||
void Notifier::sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 row)
|
||||
{
|
||||
poco_check_ptr(pVal);
|
||||
Notifier* pV = reinterpret_cast<Notifier*>(pVal);
|
||||
|
||||
if (opCode == Utility::OPERATION_INSERT)
|
||||
{
|
||||
pV->_table = pTable;
|
||||
pV->_row = row;
|
||||
pV->insert.notify(pV);
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_UPDATE)
|
||||
{
|
||||
pV->_table = pTable;
|
||||
pV->_row = row;
|
||||
pV->update.notify(pV);
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_DELETE)
|
||||
{
|
||||
pV->_table = pTable;
|
||||
pV->_row = row;
|
||||
pV->erase.notify(pV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Notifier::sqliteCommitCallbackFn(void* pVal)
|
||||
{
|
||||
Notifier* pV = reinterpret_cast<Notifier*>(pVal);
|
||||
|
||||
try
|
||||
{
|
||||
pV->commit.notify(pV);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Notifier::sqliteRollbackCallbackFn(void* pVal)
|
||||
{
|
||||
Notifier* pV = reinterpret_cast<Notifier*>(pVal);
|
||||
pV->rollback.notify(pV);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
51
vendor/POCO/Data/SQLite/src/SQLiteException.cpp
vendored
Normal file
51
vendor/POCO/Data/SQLite/src/SQLiteException.cpp
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// SQLiteException.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: SQLiteException
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
POCO_IMPLEMENT_EXCEPTION(SQLiteException, Poco::Data::DataException, "SQLite exception")
|
||||
POCO_IMPLEMENT_EXCEPTION(InvalidSQLStatementException, SQLiteException, "Invalid SQL statement")
|
||||
POCO_IMPLEMENT_EXCEPTION(InternalDBErrorException, SQLiteException, "Internal DB error")
|
||||
POCO_IMPLEMENT_EXCEPTION(DBAccessDeniedException, SQLiteException, "DB access denied")
|
||||
POCO_IMPLEMENT_EXCEPTION(ExecutionAbortedException, SQLiteException, "Execution aborted")
|
||||
POCO_IMPLEMENT_EXCEPTION(DBLockedException, SQLiteException, "DB locked")
|
||||
POCO_IMPLEMENT_EXCEPTION(TableLockedException, SQLiteException, "Table locked")
|
||||
POCO_IMPLEMENT_EXCEPTION(NoMemoryException, SQLiteException, "Out of Memory")
|
||||
POCO_IMPLEMENT_EXCEPTION(ReadOnlyException, SQLiteException, "Read only")
|
||||
POCO_IMPLEMENT_EXCEPTION(InterruptException, SQLiteException, "Interrupt")
|
||||
POCO_IMPLEMENT_EXCEPTION(IOErrorException, SQLiteException, "I/O error")
|
||||
POCO_IMPLEMENT_EXCEPTION(CorruptImageException, SQLiteException, "Corrupt image")
|
||||
POCO_IMPLEMENT_EXCEPTION(TableNotFoundException, SQLiteException, "Table not found")
|
||||
POCO_IMPLEMENT_EXCEPTION(DatabaseFullException, SQLiteException, "Database full")
|
||||
POCO_IMPLEMENT_EXCEPTION(CantOpenDBFileException, SQLiteException, "Can't open DB file")
|
||||
POCO_IMPLEMENT_EXCEPTION(LockProtocolException, SQLiteException, "Lock protocol")
|
||||
POCO_IMPLEMENT_EXCEPTION(SchemaDiffersException, SQLiteException, "Schema differs")
|
||||
POCO_IMPLEMENT_EXCEPTION(RowTooBigException, SQLiteException, "Row too big")
|
||||
POCO_IMPLEMENT_EXCEPTION(ConstraintViolationException, SQLiteException, "Constraint violation")
|
||||
POCO_IMPLEMENT_EXCEPTION(DataTypeMismatchException, SQLiteException, "Data type mismatch")
|
||||
POCO_IMPLEMENT_EXCEPTION(ParameterCountMismatchException, SQLiteException, "Parameter count mismatch")
|
||||
POCO_IMPLEMENT_EXCEPTION(InvalidLibraryUseException, SQLiteException, "Invalid library use")
|
||||
POCO_IMPLEMENT_EXCEPTION(OSFeaturesMissingException, SQLiteException, "OS features missing")
|
||||
POCO_IMPLEMENT_EXCEPTION(AuthorizationDeniedException, SQLiteException, "Authorization denied")
|
||||
POCO_IMPLEMENT_EXCEPTION(TransactionException, SQLiteException, "Transaction exception")
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
316
vendor/POCO/Data/SQLite/src/SQLiteStatementImpl.cpp
vendored
Normal file
316
vendor/POCO/Data/SQLite/src/SQLiteStatementImpl.cpp
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
//
|
||||
// SQLiteStatementImpl.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: SQLiteStatementImpl
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLiteStatementImpl.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/String.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const int SQLiteStatementImpl::POCO_SQLITE_INV_ROW_CNT = -1;
|
||||
|
||||
|
||||
SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB):
|
||||
StatementImpl(rSession),
|
||||
_pDB(pDB),
|
||||
_pStmt(0),
|
||||
_stepCalled(false),
|
||||
_nextResponse(0),
|
||||
_affectedRowCount(POCO_SQLITE_INV_ROW_CNT),
|
||||
_canBind(false),
|
||||
_isExtracted(false),
|
||||
_canCompile(true)
|
||||
{
|
||||
_columns.resize(1);
|
||||
}
|
||||
|
||||
|
||||
SQLiteStatementImpl::~SQLiteStatementImpl()
|
||||
{
|
||||
try
|
||||
{
|
||||
clear();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStatementImpl::compileImpl()
|
||||
{
|
||||
if (!_pLeftover)
|
||||
{
|
||||
_bindBegin = bindings().begin();
|
||||
}
|
||||
|
||||
std::string statement(toString());
|
||||
|
||||
sqlite3_stmt* pStmt = 0;
|
||||
const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str();
|
||||
|
||||
if (0 == std::strlen(pSql))
|
||||
throw InvalidSQLStatementException("Empty statements are illegal");
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
const char* pLeftover = 0;
|
||||
bool queryFound = false;
|
||||
|
||||
do
|
||||
{
|
||||
rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
std::string errMsg = sqlite3_errmsg(_pDB);
|
||||
Utility::throwException(_pDB, rc, errMsg);
|
||||
}
|
||||
else if (rc == SQLITE_OK && pStmt)
|
||||
{
|
||||
queryFound = true;
|
||||
}
|
||||
else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
|
||||
{
|
||||
pSql = pLeftover;
|
||||
if (std::strlen(pSql) == 0)
|
||||
{
|
||||
// empty statement or an conditional statement! like CREATE IF NOT EXISTS
|
||||
// this is valid
|
||||
queryFound = true;
|
||||
}
|
||||
}
|
||||
} while (rc == SQLITE_OK && !pStmt && !queryFound);
|
||||
|
||||
//Finalization call in clear() invalidates the pointer, so the value is remembered here.
|
||||
//For last statement in a batch (or a single statement), pLeftover == "", so the next call
|
||||
// to compileImpl() shall return false immediately when there are no more statements left.
|
||||
std::string leftOver(pLeftover);
|
||||
trimInPlace(leftOver);
|
||||
clear();
|
||||
_pStmt = pStmt;
|
||||
if (!leftOver.empty())
|
||||
{
|
||||
_pLeftover = new std::string(leftOver);
|
||||
_canCompile = true;
|
||||
}
|
||||
else _canCompile = false;
|
||||
|
||||
_pBinder = new Binder(_pStmt);
|
||||
_pExtractor = new Extractor(_pStmt);
|
||||
|
||||
if (SQLITE_DONE == _nextResponse && _isExtracted)
|
||||
{
|
||||
//if this is not the first compile and there has already been extraction
|
||||
//during previous step, switch to the next set if there is one provided
|
||||
if (hasMoreDataSets())
|
||||
{
|
||||
activateNextDataSet();
|
||||
_isExtracted = false;
|
||||
}
|
||||
}
|
||||
|
||||
int colCount = sqlite3_column_count(_pStmt);
|
||||
|
||||
if (colCount)
|
||||
{
|
||||
std::size_t curDataSet = currentDataSet();
|
||||
if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1);
|
||||
for (int i = 0; i < colCount; ++i)
|
||||
{
|
||||
MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
|
||||
_columns[curDataSet].push_back(mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStatementImpl::bindImpl()
|
||||
{
|
||||
_stepCalled = false;
|
||||
_nextResponse = 0;
|
||||
if (_pStmt == 0) return;
|
||||
|
||||
sqlite3_reset(_pStmt);
|
||||
|
||||
int paramCount = sqlite3_bind_parameter_count(_pStmt);
|
||||
if (0 == paramCount)
|
||||
{
|
||||
_canBind = false;
|
||||
return;
|
||||
}
|
||||
|
||||
BindIt bindEnd = bindings().end();
|
||||
std::size_t availableCount = 0;
|
||||
Bindings::difference_type bindCount = 0;
|
||||
Bindings::iterator it = _bindBegin;
|
||||
for (; it != bindEnd; ++it)
|
||||
{
|
||||
availableCount += (*it)->numOfColumnsHandled();
|
||||
if (availableCount <= paramCount) ++bindCount;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (availableCount < paramCount)
|
||||
throw ParameterCountMismatchException();
|
||||
|
||||
Bindings::difference_type remainingBindCount = bindEnd - _bindBegin;
|
||||
if (bindCount < remainingBindCount)
|
||||
{
|
||||
bindEnd = _bindBegin + bindCount;
|
||||
_canBind = true;
|
||||
}
|
||||
else if (bindCount > remainingBindCount)
|
||||
throw ParameterCountMismatchException();
|
||||
|
||||
std::size_t boundRowCount;
|
||||
if (_bindBegin != bindings().end())
|
||||
{
|
||||
boundRowCount = (*_bindBegin)->numOfRowsHandled();
|
||||
|
||||
Bindings::iterator oldBegin = _bindBegin;
|
||||
for (std::size_t pos = 1; _bindBegin != bindEnd && (*_bindBegin)->canBind(); ++_bindBegin)
|
||||
{
|
||||
if (boundRowCount != (*_bindBegin)->numOfRowsHandled())
|
||||
throw BindingException("Size mismatch in Bindings. All Bindings MUST have the same size");
|
||||
|
||||
(*_bindBegin)->bind(pos);
|
||||
pos += (*_bindBegin)->numOfColumnsHandled();
|
||||
}
|
||||
|
||||
if ((*oldBegin)->canBind())
|
||||
{
|
||||
//container binding will come back for more, so we must rewind
|
||||
_bindBegin = oldBegin;
|
||||
_canBind = true;
|
||||
}
|
||||
else _canBind = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStatementImpl::clear()
|
||||
{
|
||||
_columns[currentDataSet()].clear();
|
||||
_affectedRowCount = POCO_SQLITE_INV_ROW_CNT;
|
||||
|
||||
if (_pStmt)
|
||||
{
|
||||
sqlite3_finalize(_pStmt);
|
||||
_pStmt=0;
|
||||
}
|
||||
_pLeftover = 0;
|
||||
}
|
||||
|
||||
|
||||
bool SQLiteStatementImpl::hasNext()
|
||||
{
|
||||
if (_stepCalled)
|
||||
return (_nextResponse == SQLITE_ROW);
|
||||
|
||||
// _pStmt is allowed to be null for conditional SQL statements
|
||||
if (_pStmt == 0)
|
||||
{
|
||||
_stepCalled = true;
|
||||
_nextResponse = SQLITE_DONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_stepCalled = true;
|
||||
_nextResponse = sqlite3_step(_pStmt);
|
||||
|
||||
if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
|
||||
if (!sqlite3_stmt_readonly(_pStmt))
|
||||
_affectedRowCount += sqlite3_changes(_pDB);
|
||||
|
||||
if (_nextResponse != SQLITE_ROW && _nextResponse != SQLITE_OK && _nextResponse != SQLITE_DONE)
|
||||
Utility::throwException(_pDB, _nextResponse);
|
||||
|
||||
_pExtractor->reset();//clear the cached null indicators
|
||||
|
||||
return (_nextResponse == SQLITE_ROW);
|
||||
}
|
||||
|
||||
|
||||
std::size_t SQLiteStatementImpl::next()
|
||||
{
|
||||
if (SQLITE_ROW == _nextResponse)
|
||||
{
|
||||
poco_assert (columnsReturned() == sqlite3_column_count(_pStmt));
|
||||
|
||||
Extractions& extracts = extractions();
|
||||
Extractions::iterator it = extracts.begin();
|
||||
Extractions::iterator itEnd = extracts.end();
|
||||
std::size_t pos = 0; // sqlite starts with pos 0 for results!
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
(*it)->extract(pos);
|
||||
pos += (*it)->numOfColumnsHandled();
|
||||
_isExtracted = true;
|
||||
}
|
||||
_stepCalled = false;
|
||||
if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
|
||||
if (extracts.begin() != extracts.end())
|
||||
{
|
||||
_affectedRowCount += static_cast<int>((*extracts.begin())->numOfRowsHandled());
|
||||
}
|
||||
}
|
||||
else if (SQLITE_DONE == _nextResponse)
|
||||
{
|
||||
throw Poco::Data::DataException("No data received");
|
||||
}
|
||||
else
|
||||
{
|
||||
Utility::throwException(_pDB, _nextResponse, std::string("Iterator Error: trying to access the next value"));
|
||||
}
|
||||
|
||||
return 1u;
|
||||
}
|
||||
|
||||
|
||||
std::size_t SQLiteStatementImpl::columnsReturned() const
|
||||
{
|
||||
return (std::size_t) _columns[currentDataSet()].size();
|
||||
}
|
||||
|
||||
|
||||
const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const
|
||||
{
|
||||
std::size_t curDataSet = currentDataSet();
|
||||
poco_assert (pos >= 0 && pos <= _columns[curDataSet].size());
|
||||
return _columns[curDataSet][pos];
|
||||
}
|
||||
|
||||
|
||||
int SQLiteStatementImpl::affectedRowCount() const
|
||||
{
|
||||
if (_affectedRowCount != POCO_SQLITE_INV_ROW_CNT) return _affectedRowCount;
|
||||
return _pStmt == 0 || sqlite3_stmt_readonly(_pStmt) ? 0 : sqlite3_changes(_pDB);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
254
vendor/POCO/Data/SQLite/src/SessionImpl.cpp
vendored
Normal file
254
vendor/POCO/Data/SQLite/src/SessionImpl.cpp
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
//
|
||||
// SessionImpl.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: SessionImpl
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SessionImpl.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/SQLite/SQLiteStatementImpl.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Stopwatch.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
#ifndef SQLITE_OPEN_URI
|
||||
#define SQLITE_OPEN_URI 0
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const std::string SessionImpl::DEFERRED_BEGIN_TRANSACTION("BEGIN DEFERRED");
|
||||
const std::string SessionImpl::COMMIT_TRANSACTION("COMMIT");
|
||||
const std::string SessionImpl::ABORT_TRANSACTION("ROLLBACK");
|
||||
|
||||
|
||||
SessionImpl::SessionImpl(const std::string& fileName, std::size_t loginTimeout):
|
||||
Poco::Data::AbstractSessionImpl<SessionImpl>(fileName, loginTimeout),
|
||||
_connector(Connector::KEY),
|
||||
_pDB(0),
|
||||
_connected(false),
|
||||
_isTransaction(false)
|
||||
{
|
||||
open();
|
||||
setConnectionTimeout(loginTimeout);
|
||||
setProperty("handle", _pDB);
|
||||
addFeature("autoCommit",
|
||||
&SessionImpl::autoCommit,
|
||||
&SessionImpl::isAutoCommit);
|
||||
addProperty("connectionTimeout", &SessionImpl::setConnectionTimeout, &SessionImpl::getConnectionTimeout);
|
||||
}
|
||||
|
||||
|
||||
SessionImpl::~SessionImpl()
|
||||
{
|
||||
try
|
||||
{
|
||||
close();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Poco::Data::StatementImpl::Ptr SessionImpl::createStatementImpl()
|
||||
{
|
||||
poco_check_ptr (_pDB);
|
||||
return new SQLiteStatementImpl(*this, _pDB);
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::begin()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(DEFERRED_BEGIN_TRANSACTION);
|
||||
tmp.execute();
|
||||
_isTransaction = true;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::commit()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(COMMIT_TRANSACTION);
|
||||
tmp.execute();
|
||||
_isTransaction = false;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::rollback()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(ABORT_TRANSACTION);
|
||||
tmp.execute();
|
||||
_isTransaction = false;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::setTransactionIsolation(Poco::UInt32 ti)
|
||||
{
|
||||
if (ti != Session::TRANSACTION_READ_COMMITTED)
|
||||
throw Poco::InvalidArgumentException("setTransactionIsolation()");
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt32 SessionImpl::getTransactionIsolation() const
|
||||
{
|
||||
return Session::TRANSACTION_READ_COMMITTED;
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::hasTransactionIsolation(Poco::UInt32 ti) const
|
||||
{
|
||||
if (ti == Session::TRANSACTION_READ_COMMITTED) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::isTransactionIsolation(Poco::UInt32 ti) const
|
||||
{
|
||||
if (ti == Session::TRANSACTION_READ_COMMITTED) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::open(const std::string& connect)
|
||||
{
|
||||
if (connect != connectionString())
|
||||
{
|
||||
if (isConnected())
|
||||
throw InvalidAccessException("Session already connected");
|
||||
|
||||
if (!connect.empty())
|
||||
setConnectionString(connect);
|
||||
}
|
||||
|
||||
poco_assert_dbg (!connectionString().empty());
|
||||
|
||||
try
|
||||
{
|
||||
int rc = 0;
|
||||
size_t tout = getLoginTimeout();
|
||||
Stopwatch sw; sw.start();
|
||||
while (true)
|
||||
{
|
||||
rc = sqlite3_open_v2(connectionString().c_str(), &_pDB,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
|
||||
if (rc == SQLITE_OK) break;
|
||||
if (sw.elapsedSeconds() >= tout)
|
||||
{
|
||||
Utility::throwException(_pDB, rc);
|
||||
}
|
||||
Thread::sleep(10);
|
||||
close();
|
||||
}
|
||||
}
|
||||
catch (SQLiteException& ex)
|
||||
{
|
||||
close();
|
||||
throw ConnectionFailedException(ex.displayText());
|
||||
}
|
||||
|
||||
_connected = true;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::close()
|
||||
{
|
||||
if (_pDB)
|
||||
{
|
||||
sqlite3_close_v2(_pDB);
|
||||
_pDB = 0;
|
||||
}
|
||||
|
||||
_connected = false;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::isConnected() const
|
||||
{
|
||||
return _connected;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::setConnectionTimeout(std::size_t timeout)
|
||||
{
|
||||
int tout = static_cast<int>(1000 * timeout);
|
||||
int rc = sqlite3_busy_timeout(_pDB, tout);
|
||||
if (rc != 0) Utility::throwException(_pDB, rc);
|
||||
_timeout = tout;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::setConnectionTimeout(const std::string& prop, const Poco::Any& value)
|
||||
{
|
||||
setConnectionTimeout(Poco::RefAnyCast<std::size_t>(value));
|
||||
}
|
||||
|
||||
|
||||
Poco::Any SessionImpl::getConnectionTimeout(const std::string& prop) const
|
||||
{
|
||||
return Poco::Any(_timeout/1000);
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::autoCommit(const std::string&, bool)
|
||||
{
|
||||
// The problem here is to decide whether to call commit or rollback
|
||||
// when autocommit is set to true. Hence, it is best not to implement
|
||||
// this explicit call and only implicitly support autocommit setting.
|
||||
throw NotImplementedException(
|
||||
"SQLite autocommit is implicit with begin/commit/rollback.");
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::isAutoCommit(const std::string&) const
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
return (0 != sqlite3_get_autocommit(_pDB));
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Utility::dbHandle() has been moved here from Utility.cpp
|
||||
// as a workaround for a failing AnyCast with Clang.
|
||||
// See <https://github.com/pocoproject/poco/issues/578>
|
||||
// for a discussion.
|
||||
sqlite3* Utility::dbHandle(const Session& session)
|
||||
{
|
||||
return AnyCast<sqlite3*>(session.getProperty("handle"));
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
346
vendor/POCO/Data/SQLite/src/Utility.cpp
vendored
Normal file
346
vendor/POCO/Data/SQLite/src/Utility.cpp
vendored
Normal file
@@ -0,0 +1,346 @@
|
||||
//
|
||||
// Utility.cpp
|
||||
//
|
||||
// Library: Data/SQLite
|
||||
// Package: SQLite
|
||||
// Module: Utility
|
||||
//
|
||||
// Implementation of Utility
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/Exception.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SQLITE_OPEN_URI
|
||||
#define SQLITE_OPEN_URI 0
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const int Utility::THREAD_MODE_SINGLE = SQLITE_CONFIG_SINGLETHREAD;
|
||||
const int Utility::THREAD_MODE_MULTI = SQLITE_CONFIG_MULTITHREAD;
|
||||
const int Utility::THREAD_MODE_SERIAL = SQLITE_CONFIG_SERIALIZED;
|
||||
int Utility::_threadMode =
|
||||
#if (SQLITE_THREADSAFE == 0)
|
||||
SQLITE_CONFIG_SINGLETHREAD;
|
||||
#elif (SQLITE_THREADSAFE == 1)
|
||||
SQLITE_CONFIG_SERIALIZED;
|
||||
#elif (SQLITE_THREADSAFE == 2)
|
||||
SQLITE_CONFIG_MULTITHREAD;
|
||||
#endif
|
||||
|
||||
const int Utility::OPERATION_INSERT = SQLITE_INSERT;
|
||||
const int Utility::OPERATION_DELETE = SQLITE_DELETE;
|
||||
const int Utility::OPERATION_UPDATE = SQLITE_UPDATE;
|
||||
|
||||
const std::string Utility::SQLITE_DATE_FORMAT = "%Y-%m-%d";
|
||||
const std::string Utility::SQLITE_TIME_FORMAT = "%H:%M:%S";
|
||||
Utility::TypeMap Utility::_types;
|
||||
Poco::Mutex Utility::_mutex;
|
||||
|
||||
|
||||
Utility::SQLiteMutex::SQLiteMutex(sqlite3* pDB): _pMutex((pDB) ? sqlite3_db_mutex(pDB) : 0)
|
||||
{
|
||||
if (_pMutex)
|
||||
sqlite3_mutex_enter(_pMutex);
|
||||
}
|
||||
|
||||
|
||||
Utility::SQLiteMutex::~SQLiteMutex()
|
||||
{
|
||||
if (_pMutex)
|
||||
sqlite3_mutex_leave(_pMutex);
|
||||
}
|
||||
|
||||
|
||||
Utility::Utility()
|
||||
{
|
||||
if (_types.empty())
|
||||
{
|
||||
_types.insert(TypeMap::value_type("", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("BOOL", MetaColumn::FDT_BOOL));
|
||||
_types.insert(TypeMap::value_type("BOOLEAN", MetaColumn::FDT_BOOL));
|
||||
_types.insert(TypeMap::value_type("BIT", MetaColumn::FDT_BOOL));
|
||||
_types.insert(TypeMap::value_type("UINT8", MetaColumn::FDT_UINT8));
|
||||
_types.insert(TypeMap::value_type("UTINY", MetaColumn::FDT_UINT8));
|
||||
_types.insert(TypeMap::value_type("UINTEGER8", MetaColumn::FDT_UINT8));
|
||||
_types.insert(TypeMap::value_type("INT8", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("TINY", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("INTEGER8", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("UINT16", MetaColumn::FDT_UINT16));
|
||||
_types.insert(TypeMap::value_type("USHORT", MetaColumn::FDT_UINT16));
|
||||
_types.insert(TypeMap::value_type("UINTEGER16", MetaColumn::FDT_UINT16));
|
||||
_types.insert(TypeMap::value_type("INT16", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("SHORT", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("INTEGER16", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("UINT", MetaColumn::FDT_UINT32));
|
||||
_types.insert(TypeMap::value_type("UINT32", MetaColumn::FDT_UINT32));
|
||||
_types.insert(TypeMap::value_type("UINTEGER", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("UINTEGER32", MetaColumn::FDT_UINT32));
|
||||
_types.insert(TypeMap::value_type("INT", MetaColumn::FDT_INT32));
|
||||
_types.insert(TypeMap::value_type("INT32", MetaColumn::FDT_INT32));
|
||||
_types.insert(TypeMap::value_type("INTEGER", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("INTEGER32", MetaColumn::FDT_INT32));
|
||||
_types.insert(TypeMap::value_type("UINT64", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("ULONG", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("UINTEGER64", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("INT64", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("LONG", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("INTEGER64", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("TINYINT", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("SMALLINT", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("BIGINT", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("LONGINT", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("COUNTER", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("AUTOINCREMENT", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("REAL", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("FLOA", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("FLOAT", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("DOUB", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("DOUBLE", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("DECIMAL", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("NUMERIC", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("CHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("CLOB", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("TEXT", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("VARCHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NCHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NCLOB", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NTEXT", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NVARCHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("LONGVARCHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("BLOB", MetaColumn::FDT_BLOB));
|
||||
_types.insert(TypeMap::value_type("DATE", MetaColumn::FDT_DATE));
|
||||
_types.insert(TypeMap::value_type("TIME", MetaColumn::FDT_TIME));
|
||||
_types.insert(TypeMap::value_type("DATETIME", MetaColumn::FDT_TIMESTAMP));
|
||||
_types.insert(TypeMap::value_type("TIMESTAMP", MetaColumn::FDT_TIMESTAMP));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string Utility::lastError(sqlite3* pDB)
|
||||
{
|
||||
std::string errStr;
|
||||
SQLiteMutex m(pDB);
|
||||
const char* pErr = sqlite3_errmsg(pDB);
|
||||
if (pErr) errStr = pErr;
|
||||
return errStr;
|
||||
}
|
||||
|
||||
|
||||
MetaColumn::ColumnDataType Utility::getColumnType(sqlite3_stmt* pStmt, std::size_t pos)
|
||||
{
|
||||
poco_assert_dbg (pStmt);
|
||||
|
||||
// Ensure statics are initialized
|
||||
{
|
||||
Poco::Mutex::ScopedLock lock(_mutex);
|
||||
static Utility u;
|
||||
}
|
||||
|
||||
const char* pc = sqlite3_column_decltype(pStmt, (int) pos);
|
||||
std::string sqliteType = pc ? pc : "";
|
||||
Poco::toUpperInPlace(sqliteType);
|
||||
sqliteType = sqliteType.substr(0, sqliteType.find_first_of(" ("));
|
||||
|
||||
TypeMap::const_iterator it = _types.find(Poco::trimInPlace(sqliteType));
|
||||
if (_types.end() == it) throw Poco::NotFoundException();
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
void Utility::throwException(sqlite3* pDB, int rc, const std::string& addErrMsg)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case SQLITE_OK:
|
||||
break;
|
||||
case SQLITE_ERROR:
|
||||
throw InvalidSQLStatementException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_INTERNAL:
|
||||
throw InternalDBErrorException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_PERM:
|
||||
throw DBAccessDeniedException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_ABORT:
|
||||
throw ExecutionAbortedException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_BUSY:
|
||||
case SQLITE_BUSY_RECOVERY:
|
||||
#if defined(SQLITE_BUSY_SNAPSHOT)
|
||||
case SQLITE_BUSY_SNAPSHOT:
|
||||
#endif
|
||||
throw DBLockedException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_LOCKED:
|
||||
throw TableLockedException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_NOMEM:
|
||||
throw NoMemoryException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_READONLY:
|
||||
throw ReadOnlyException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_INTERRUPT:
|
||||
throw InterruptException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_IOERR:
|
||||
throw IOErrorException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_CORRUPT:
|
||||
throw CorruptImageException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_NOTFOUND:
|
||||
throw TableNotFoundException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_FULL:
|
||||
throw DatabaseFullException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_CANTOPEN:
|
||||
throw CantOpenDBFileException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_PROTOCOL:
|
||||
throw LockProtocolException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_EMPTY:
|
||||
throw InternalDBErrorException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_SCHEMA:
|
||||
throw SchemaDiffersException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_TOOBIG:
|
||||
throw RowTooBigException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_CONSTRAINT:
|
||||
throw ConstraintViolationException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_MISMATCH:
|
||||
throw DataTypeMismatchException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_MISUSE:
|
||||
throw InvalidLibraryUseException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_NOLFS:
|
||||
throw OSFeaturesMissingException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_AUTH:
|
||||
throw AuthorizationDeniedException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_FORMAT:
|
||||
throw CorruptImageException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_NOTADB:
|
||||
throw CorruptImageException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_RANGE:
|
||||
throw InvalidSQLStatementException(lastError(pDB), addErrMsg);
|
||||
case SQLITE_ROW:
|
||||
break; // sqlite_step() has another row ready
|
||||
case SQLITE_DONE:
|
||||
break; // sqlite_step() has finished executing
|
||||
default:
|
||||
throw SQLiteException(Poco::format("Unknown error code: %d", rc), addErrMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Utility::fileToMemory(sqlite3* pInMemory, const std::string& fileName)
|
||||
{
|
||||
int rc;
|
||||
sqlite3* pFile;
|
||||
sqlite3_backup* pBackup;
|
||||
|
||||
rc = sqlite3_open_v2(fileName.c_str(), &pFile, SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, NULL);
|
||||
if(rc == SQLITE_OK )
|
||||
{
|
||||
pBackup = sqlite3_backup_init(pInMemory, "main", pFile, "main");
|
||||
if( pBackup )
|
||||
{
|
||||
sqlite3_backup_step(pBackup, -1);
|
||||
sqlite3_backup_finish(pBackup);
|
||||
}
|
||||
rc = sqlite3_errcode(pFile);
|
||||
}
|
||||
|
||||
sqlite3_close(pFile);
|
||||
return SQLITE_OK == rc;
|
||||
}
|
||||
|
||||
|
||||
bool Utility::memoryToFile(const std::string& fileName, sqlite3* pInMemory)
|
||||
{
|
||||
int rc;
|
||||
sqlite3* pFile;
|
||||
sqlite3_backup* pBackup;
|
||||
|
||||
rc = sqlite3_open_v2(fileName.c_str(), &pFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
|
||||
if(rc == SQLITE_OK )
|
||||
{
|
||||
pBackup = sqlite3_backup_init(pFile, "main", pInMemory, "main");
|
||||
if( pBackup )
|
||||
{
|
||||
sqlite3_backup_step(pBackup, -1);
|
||||
sqlite3_backup_finish(pBackup);
|
||||
}
|
||||
rc = sqlite3_errcode(pFile);
|
||||
}
|
||||
|
||||
sqlite3_close(pFile);
|
||||
return SQLITE_OK == rc;
|
||||
}
|
||||
|
||||
|
||||
bool Utility::isThreadSafe()
|
||||
{
|
||||
return 0 != sqlite3_threadsafe();
|
||||
}
|
||||
|
||||
|
||||
int Utility::getThreadMode()
|
||||
{
|
||||
return _threadMode;
|
||||
}
|
||||
|
||||
|
||||
bool Utility::setThreadMode(int mode)
|
||||
{
|
||||
#if (SQLITE_THREADSAFE != 0)
|
||||
if (SQLITE_OK == sqlite3_shutdown())
|
||||
{
|
||||
if (SQLITE_OK == sqlite3_config(mode))
|
||||
{
|
||||
_threadMode = mode;
|
||||
if (SQLITE_OK == sqlite3_initialize())
|
||||
return true;
|
||||
}
|
||||
sqlite3_initialize();
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
typedef void(*pF)(void*, int, const char*, const char*, sqlite3_int64);
|
||||
return sqlite3_update_hook(pDB, reinterpret_cast<pF>(callbackFn), pParam);
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
return sqlite3_commit_hook(pDB, callbackFn, pParam);
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
return sqlite3_rollback_hook(pDB, callbackFn, pParam);
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Utility::dbHandle() has been moved to SessionImpl.cpp,
|
||||
// as a workaround for a failing AnyCast with Clang.
|
||||
// See <https://github.com/pocoproject/poco/issues/578>
|
||||
// for a discussion.
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
228449
vendor/POCO/Data/SQLite/src/sqlite3.c
vendored
Normal file
228449
vendor/POCO/Data/SQLite/src/sqlite3.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12084
vendor/POCO/Data/SQLite/src/sqlite3.h
vendored
Normal file
12084
vendor/POCO/Data/SQLite/src/sqlite3.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user