255 lines
6.8 KiB
C++
255 lines
6.8 KiB
C++
//
|
|
// Utility.h
|
|
//
|
|
// Library: Data/SQLite
|
|
// Package: SQLite
|
|
// Module: Utility
|
|
//
|
|
// Definition of Utility.
|
|
//
|
|
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
|
// and Contributors.
|
|
//
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
|
|
|
|
#ifndef SQLite_Utility_INCLUDED
|
|
#define SQLite_Utility_INCLUDED
|
|
|
|
|
|
#include "Poco/Data/SQLite/SQLite.h"
|
|
#include "Poco/Data/MetaColumn.h"
|
|
#include "Poco/Data/Session.h"
|
|
#include "Poco/Mutex.h"
|
|
#include "Poco/Types.h"
|
|
#include <map>
|
|
|
|
|
|
extern "C"
|
|
{
|
|
typedef struct sqlite3 sqlite3;
|
|
typedef struct sqlite3_stmt sqlite3_stmt;
|
|
typedef struct sqlite3_mutex* _pMutex;
|
|
}
|
|
|
|
|
|
namespace Poco {
|
|
namespace Data {
|
|
namespace SQLite {
|
|
|
|
|
|
class SQLite_API Utility
|
|
/// Various utility functions for SQLite.
|
|
{
|
|
public:
|
|
|
|
// SQLite Transaction type
|
|
static const std::string TRANSACTION_TYPE_PROPERTY_KEY;
|
|
|
|
enum class TransactionType
|
|
{
|
|
DEFERRED,
|
|
EXCLUSIVE,
|
|
IMMEDIATE
|
|
};
|
|
|
|
static const std::string SQLITE_DATE_FORMAT;
|
|
static const std::string SQLITE_TIME_FORMAT;
|
|
typedef std::map<std::string, MetaColumn::ColumnDataType> TypeMap;
|
|
|
|
static const int THREAD_MODE_SINGLE;
|
|
static const int THREAD_MODE_MULTI;
|
|
static const int THREAD_MODE_SERIAL;
|
|
|
|
static const int OPERATION_INSERT;
|
|
static const int OPERATION_DELETE;
|
|
static const int OPERATION_UPDATE;
|
|
|
|
static sqlite3* dbHandle(const Session& session);
|
|
/// Returns native DB handle.
|
|
|
|
static std::string lastError(sqlite3* pDB);
|
|
/// Retreives the last error code from sqlite and converts it to a string.
|
|
|
|
static std::string lastError(const Session& session);
|
|
/// Retreives the last error code from sqlite and converts it to a string.
|
|
|
|
static void throwException(sqlite3* pDB, int rc, const std::string& addErrMsg = std::string());
|
|
/// Throws for an error code the appropriate exception
|
|
|
|
static MetaColumn::ColumnDataType getColumnType(sqlite3_stmt* pStmt, std::size_t pos);
|
|
/// Returns column data type.
|
|
|
|
static bool fileToMemory(sqlite3* pInMemory, const std::string& fileName);
|
|
/// Loads the contents of a database file on disk into an opened
|
|
/// database in memory.
|
|
///
|
|
/// Returns true if succesful.
|
|
|
|
static bool fileToMemory(const Session& session, const std::string& fileName);
|
|
/// Loads the contents of a database file on disk into an opened
|
|
/// database in memory.
|
|
///
|
|
/// Returns true if succesful.
|
|
|
|
static bool memoryToFile(const std::string& fileName, sqlite3* pInMemory);
|
|
/// Saves the contents of an opened database in memory to the
|
|
/// database on disk.
|
|
///
|
|
/// Returns true if succesful.
|
|
|
|
static bool memoryToFile(const std::string& fileName, const Session& session);
|
|
/// Saves the contents of an opened database in memory to the
|
|
/// database on disk.
|
|
///
|
|
/// Returns true if succesful.
|
|
|
|
static bool isThreadSafe();
|
|
/// Returns true if SQLite was compiled in multi-thread or serialized mode.
|
|
/// See http://www.sqlite.org/c3ref/threadsafe.html for details.
|
|
///
|
|
/// Returns true if succesful
|
|
|
|
static bool setThreadMode(int mode);
|
|
/// Sets the threading mode to single, multi or serialized.
|
|
/// See http://www.sqlite.org/threadsafe.html for details.
|
|
///
|
|
/// Returns true if succesful
|
|
|
|
static int getThreadMode();
|
|
/// Returns the thread mode.
|
|
|
|
typedef void(*UpdateCallbackType)(void*, int, const char*, const char*, Poco::Int64);
|
|
/// Update callback function type.
|
|
|
|
typedef int(*CommitCallbackType)(void*);
|
|
/// Commit callback function type.
|
|
|
|
typedef void(*RollbackCallbackType)(void*);
|
|
/// Rollback callback function type.
|
|
|
|
template <typename T, typename CBT>
|
|
static bool registerUpdateHandler(sqlite3* pDB, CBT callbackFn, T* pParam)
|
|
/// Registers the callback for (1)(insert, delete, update), (2)(commit) or
|
|
/// or (3)(rollback) events. Only one function per group can be registered
|
|
/// at a time. Registration is not thread-safe. Storage pointed to by pParam
|
|
/// must remain valid as long as registration is active. Registering with
|
|
/// callbackFn set to zero disables notifications.
|
|
///
|
|
/// See http://www.sqlite.org/c3ref/update_hook.html and
|
|
/// http://www.sqlite.org/c3ref/commit_hook.html for details.
|
|
{
|
|
typedef std::pair<CBT, T*> CBPair;
|
|
typedef std::multimap<sqlite3*, CBPair> CBMap;
|
|
typedef typename CBMap::iterator CBMapIt;
|
|
typedef std::pair<CBMapIt, CBMapIt> CBMapItPair;
|
|
|
|
static CBMap retMap;
|
|
T* pRet = reinterpret_cast<T*>(eventHookRegister(pDB, callbackFn, pParam));
|
|
|
|
if (pRet == 0)
|
|
{
|
|
if (retMap.find(pDB) == retMap.end())
|
|
{
|
|
retMap.insert(std::make_pair(pDB, CBPair(callbackFn, pParam)));
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CBMapItPair retMapRange = retMap.equal_range(pDB);
|
|
for (CBMapIt it = retMapRange.first; it != retMapRange.second; ++it)
|
|
{
|
|
poco_assert (it->second.first != 0);
|
|
if ((callbackFn == 0) && (*pRet == *it->second.second))
|
|
{
|
|
retMap.erase(it);
|
|
return true;
|
|
}
|
|
|
|
if ((callbackFn == it->second.first) && (*pRet == *it->second.second))
|
|
{
|
|
it->second.second = pParam;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <typename T, typename CBT>
|
|
static bool registerUpdateHandler(const Session& session, CBT callbackFn, T* pParam)
|
|
/// Registers the callback by calling registerUpdateHandler(sqlite3*, CBT, T*).
|
|
{
|
|
return registerUpdateHandler(dbHandle(session), callbackFn, pParam);
|
|
}
|
|
|
|
class SQLiteMutex
|
|
{
|
|
public:
|
|
SQLiteMutex(sqlite3* pDB);
|
|
~SQLiteMutex();
|
|
|
|
private:
|
|
SQLiteMutex();
|
|
sqlite3_mutex* _pMutex;
|
|
};
|
|
|
|
private:
|
|
Utility();
|
|
/// Maps SQLite column declared types to Poco::Data types through
|
|
/// static TypeMap member.
|
|
///
|
|
/// Note: SQLite is type-agnostic and it is the end-user responsibility
|
|
/// to ensure that column declared data type corresponds to the type of
|
|
/// data actually held in the database.
|
|
///
|
|
/// Column types are case-insensitive.
|
|
|
|
Utility(const Utility&);
|
|
Utility& operator = (const Utility&);
|
|
|
|
static void* eventHookRegister(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam);
|
|
static void* eventHookRegister(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam);
|
|
static void* eventHookRegister(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam);
|
|
|
|
static TypeMap _types;
|
|
static Poco::Mutex _mutex;
|
|
static int _threadMode;
|
|
};
|
|
|
|
|
|
using TransactionType = Utility::TransactionType;
|
|
|
|
|
|
//
|
|
// inlines
|
|
//
|
|
inline std::string Utility::lastError(const Session& session)
|
|
{
|
|
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
|
return lastError(dbHandle(session));
|
|
}
|
|
|
|
|
|
inline bool Utility::memoryToFile(const std::string& fileName, const Session& session)
|
|
{
|
|
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
|
return memoryToFile(fileName, dbHandle(session));
|
|
}
|
|
|
|
|
|
inline bool Utility::fileToMemory(const Session& session, const std::string& fileName)
|
|
{
|
|
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
|
return fileToMemory(dbHandle(session), fileName);
|
|
}
|
|
|
|
|
|
} } } // namespace Poco::Data::SQLite
|
|
|
|
|
|
#endif // SQLite_Utility_INCLUDED
|