SQLite event notifier
Notifier is SQLite DB event (insert, update, delete, commit, rollback) callback wrapper.
This commit is contained in:
Родитель
f756d995d2
Коммит
6943505634
|
@ -14,7 +14,7 @@ SYSFLAGS += -DSQLITE_THREADSAFE=1 -DSQLITE_DISABLE_LFS \
|
|||
-DSQLITE_OMIT_UTF16 -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_COMPLETE \
|
||||
-DSQLITE_OMIT_TCL_VARIABLE -DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
objects = Binder Extractor SessionImpl Connector \
|
||||
objects = Binder Extractor Notifier SessionImpl Connector \
|
||||
SQLiteException SQLiteStatementImpl Utility
|
||||
|
||||
sqlite_objects = sqlite3
|
||||
|
|
|
@ -438,6 +438,8 @@
|
|||
RelativePath=".\include\Poco\Data\SQLite\Connector.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Extractor.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Notifier.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\SessionImpl.h"/>
|
||||
<File
|
||||
|
@ -457,6 +459,8 @@
|
|||
RelativePath=".\src\Connector.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Extractor.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Notifier.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\SessionImpl.cpp"/>
|
||||
<File
|
||||
|
|
|
@ -370,6 +370,8 @@
|
|||
RelativePath=".\include\Poco\Data\SQLite\Connector.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Extractor.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Notifier.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\SessionImpl.h"/>
|
||||
<File
|
||||
|
@ -389,6 +391,8 @@
|
|||
RelativePath=".\src\Connector.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Extractor.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Notifier.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\SessionImpl.cpp"/>
|
||||
<File
|
||||
|
|
|
@ -391,6 +391,8 @@
|
|||
RelativePath=".\include\Poco\Data\SQLite\Connector.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Extractor.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Notifier.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\SessionImpl.h"/>
|
||||
<File
|
||||
|
@ -410,6 +412,8 @@
|
|||
RelativePath=".\src\Connector.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Extractor.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Notifier.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\SessionImpl.cpp"/>
|
||||
<File
|
||||
|
|
|
@ -390,6 +390,8 @@
|
|||
RelativePath=".\include\Poco\Data\SQLite\Connector.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Extractor.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\Notifier.h"/>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLite\SessionImpl.h"/>
|
||||
<File
|
||||
|
@ -409,6 +411,8 @@
|
|||
RelativePath=".\src\Connector.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Extractor.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\Notifier.cpp"/>
|
||||
<File
|
||||
RelativePath=".\src\SessionImpl.cpp"/>
|
||||
<File
|
||||
|
|
|
@ -270,6 +270,7 @@
|
|||
<ClInclude Include="include\Poco\Data\SQLite\Binder.h" />
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Connector.h" />
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Extractor.h" />
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Notifier.h" />
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SessionImpl.h" />
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SQLite.h" />
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SQLiteException.h" />
|
||||
|
@ -281,6 +282,7 @@
|
|||
<ClCompile Include="src\Binder.cpp" />
|
||||
<ClCompile Include="src\Connector.cpp" />
|
||||
<ClCompile Include="src\Extractor.cpp" />
|
||||
<ClCompile Include="src\Notifier.cpp" />
|
||||
<ClCompile Include="src\SessionImpl.cpp" />
|
||||
<ClCompile Include="src\SQLiteException.cpp" />
|
||||
<ClCompile Include="src\SQLiteStatementImpl.cpp" />
|
||||
|
|
|
@ -48,6 +48,9 @@
|
|||
<ClInclude Include="src\sqlite3.h">
|
||||
<Filter>3rdparty\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Notifier.h">
|
||||
<Filter>SQLite\Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Binder.cpp">
|
||||
|
@ -74,5 +77,8 @@
|
|||
<ClCompile Include="src\sqlite3.c">
|
||||
<Filter>3rdparty\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Notifier.cpp">
|
||||
<Filter>SQLite\Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -276,6 +276,7 @@
|
|||
<ClInclude Include="include\Poco\Data\SQLite\Binder.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Connector.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Extractor.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Notifier.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SessionImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SQLite.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SQLiteException.h"/>
|
||||
|
@ -287,6 +288,7 @@
|
|||
<ClCompile Include="src\Binder.cpp"/>
|
||||
<ClCompile Include="src\Connector.cpp"/>
|
||||
<ClCompile Include="src\Extractor.cpp"/>
|
||||
<ClCompile Include="src\Notifier.cpp"/>
|
||||
<ClCompile Include="src\SessionImpl.cpp"/>
|
||||
<ClCompile Include="src\SQLiteException.cpp"/>
|
||||
<ClCompile Include="src\SQLiteStatementImpl.cpp"/>
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
<ClInclude Include="include\Poco\Data\SQLite\Extractor.h">
|
||||
<Filter>SQLite\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Notifier.h">
|
||||
<Filter>SQLite\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SessionImpl.h">
|
||||
<Filter>SQLite\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -59,6 +62,9 @@
|
|||
<ClCompile Include="src\Extractor.cpp">
|
||||
<Filter>SQLite\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Notifier.cpp">
|
||||
<Filter>SQLite\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SessionImpl.cpp">
|
||||
<Filter>SQLite\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -274,6 +274,7 @@
|
|||
<ClInclude Include="include\Poco\Data\SQLite\Binder.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Connector.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Extractor.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Notifier.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SessionImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SQLite.h"/>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SQLiteException.h"/>
|
||||
|
@ -285,6 +286,7 @@
|
|||
<ClCompile Include="src\Binder.cpp"/>
|
||||
<ClCompile Include="src\Connector.cpp"/>
|
||||
<ClCompile Include="src\Extractor.cpp"/>
|
||||
<ClCompile Include="src\Notifier.cpp"/>
|
||||
<ClCompile Include="src\SessionImpl.cpp"/>
|
||||
<ClCompile Include="src\SQLiteException.cpp"/>
|
||||
<ClCompile Include="src\SQLiteStatementImpl.cpp"/>
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
<ClInclude Include="include\Poco\Data\SQLite\Extractor.h">
|
||||
<Filter>SQLite\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\Notifier.h">
|
||||
<Filter>SQLite\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Data\SQLite\SessionImpl.h">
|
||||
<Filter>SQLite\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -59,6 +62,9 @@
|
|||
<ClCompile Include="src\Extractor.cpp">
|
||||
<Filter>SQLite\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Notifier.cpp">
|
||||
<Filter>SQLite\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SessionImpl.cpp">
|
||||
<Filter>SQLite\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
//
|
||||
// Notifier.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/Notifier.h#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Notifier
|
||||
//
|
||||
// Definition of Notifier.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef SQLite_Notifier_INCLUDED
|
||||
#define SQLite_Notifier_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Types.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/BasicEvent.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API Notifier
|
||||
/// Notifier is a wrapper for SQLite callback calls. It supports event callbacks
|
||||
/// for insert, update, delete, commit and rollback events. While (un)registering
|
||||
/// callbacks is thread-safe, execution of the callbacks themselves are not;
|
||||
/// it is the user's responsibility to ensure the thread-safey of the functions
|
||||
/// they provide as callback target. Additionally, commit callbacks may prevent
|
||||
/// database transactions from succeeding (see sqliteCommitCallbackFn documentation
|
||||
/// for details).
|
||||
///
|
||||
/// There can be only one set of callbacks per session (i.e. registering a new
|
||||
/// callback automatically unregisters the previous one). All callbacks are
|
||||
/// registered and enabled at Notifier contruction time and can be disabled
|
||||
/// at a later point time.
|
||||
{
|
||||
public:
|
||||
typedef unsigned char EnabledEventType;
|
||||
/// A type definition for events-enabled bitmap.
|
||||
|
||||
typedef Poco::BasicEvent<void> Event;
|
||||
|
||||
//
|
||||
// Events
|
||||
//
|
||||
Event update;
|
||||
Event insert;
|
||||
Event erase;
|
||||
Event commit;
|
||||
Event rollback;
|
||||
|
||||
// Event types.
|
||||
static const EnabledEventType SQLITE_NOTIFY_UPDATE = 1;
|
||||
static const EnabledEventType SQLITE_NOTIFY_COMMIT = 2;
|
||||
static const EnabledEventType SQLITE_NOTIFY_ROLLBACK = 4;
|
||||
|
||||
Notifier(const Session& session,
|
||||
EnabledEventType enabled = SQLITE_NOTIFY_UPDATE | SQLITE_NOTIFY_COMMIT | SQLITE_NOTIFY_ROLLBACK);
|
||||
/// Creates a Notifier and enables all callbacks.
|
||||
|
||||
Notifier(const Session& session,
|
||||
const Any& value,
|
||||
EnabledEventType enabled = SQLITE_NOTIFY_UPDATE | SQLITE_NOTIFY_COMMIT | SQLITE_NOTIFY_ROLLBACK);
|
||||
/// Creates a Notifier, assigns the value to the internal storage and and enables all callbacks.
|
||||
|
||||
~Notifier();
|
||||
/// Disables all callbacks and destroys the Notifier.
|
||||
|
||||
bool enableUpdate();
|
||||
/// Enables update callbacks.
|
||||
|
||||
bool disableUpdate();
|
||||
/// Disables update callbacks.
|
||||
|
||||
bool updateEnabled() const;
|
||||
/// Returns true if update callbacks are enabled, false otherwise.
|
||||
|
||||
bool enableCommit();
|
||||
/// Enables commit callbacks.
|
||||
|
||||
bool disableCommit();
|
||||
/// Disables commit callbacks.
|
||||
|
||||
bool commitEnabled() const;
|
||||
/// Returns true if update callbacks are enabled, false otherwise.
|
||||
|
||||
bool enableRollback();
|
||||
/// Enables rollback callbacks.
|
||||
|
||||
bool disableRollback();
|
||||
/// Disables rollback callbacks.
|
||||
|
||||
bool rollbackEnabled() const;
|
||||
/// Returns true if rollback callbacks are enabled, false otherwise.
|
||||
|
||||
bool enableAll();
|
||||
/// Enables all callbacks.
|
||||
|
||||
bool disableAll();
|
||||
/// Disables all callbacks.
|
||||
|
||||
static void sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 row);
|
||||
/// Update callback event dispatcher. Determines the type of the event, updates the row number
|
||||
/// and triggers the event.
|
||||
|
||||
static int sqliteCommitCallbackFn(void* pVal);
|
||||
/// Commit callback event dispatcher. If an exception occurs, it is catched inside this function,
|
||||
/// non-zero value is returned, which causes SQLite engine to turn commit into a rollback.
|
||||
/// Therefore, callers should check for return value - if it is zero, callback completed succesfuly
|
||||
/// and transaction was committed.
|
||||
|
||||
static void sqliteRollbackCallbackFn(void* pVal);
|
||||
/// Rollback callback event dispatcher.
|
||||
|
||||
bool operator == (const Notifier& other) const;
|
||||
/// Equality operator. Compares value, row and database handles and
|
||||
/// returns true iff all are equal.
|
||||
|
||||
Poco::Int64 getRow() const;
|
||||
/// Returns the row number.
|
||||
|
||||
void setRow(Poco::Int64 row);
|
||||
/// Sets the row number.
|
||||
|
||||
const Poco::Dynamic::Var& getValue() const;
|
||||
/// Returns the value.
|
||||
|
||||
template <typename T>
|
||||
inline void setValue(const T& val)
|
||||
/// Sets the value.
|
||||
{
|
||||
_value = val;
|
||||
}
|
||||
|
||||
private:
|
||||
Notifier();
|
||||
Notifier(const Notifier&);
|
||||
Notifier& operator=(const Notifier&);
|
||||
|
||||
const Session& _session;
|
||||
Poco::Dynamic::Var _value;
|
||||
Poco::Int64 _row;
|
||||
EnabledEventType _enabledEvents;
|
||||
Poco::Mutex _mutex;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline bool Notifier::operator == (const Notifier& other) const
|
||||
{
|
||||
return _value == other._value &&
|
||||
_row == other._row &&
|
||||
Utility::dbHandle(_session) == Utility::dbHandle(other._session);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::Int64 Notifier::getRow() const
|
||||
{
|
||||
return _row;
|
||||
}
|
||||
|
||||
|
||||
inline void Notifier::setRow(Poco::Int64 row)
|
||||
/// Sets the row number.
|
||||
{
|
||||
_row = row;
|
||||
}
|
||||
|
||||
|
||||
inline const Poco::Dynamic::Var& Notifier::getValue() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // SQLite_Notifier_INCLUDED
|
|
@ -0,0 +1,214 @@
|
|||
//
|
||||
// Notifier.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/Notifier.cpp#5 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Notifier
|
||||
//
|
||||
// Implementation of Notifier
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#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()
|
||||
{
|
||||
disableAll();
|
||||
}
|
||||
|
||||
|
||||
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->_row = row;
|
||||
pV->insert.notify(pV);
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_UPDATE)
|
||||
{
|
||||
pV->_row = row;
|
||||
pV->update.notify(pV);
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_DELETE)
|
||||
{
|
||||
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
|
|
@ -297,10 +297,8 @@ bool Utility::setThreadMode(int mode)
|
|||
}
|
||||
sqlite3_initialize();
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "Poco/Data/SessionFactory.h"
|
||||
#include "Poco/Data/SQLite/Connector.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/SQLite/Notifier.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/Data/TypeHandler.h"
|
||||
#include "Poco/Nullable.h"
|
||||
|
@ -60,6 +61,7 @@
|
|||
#include "Poco/Exception.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/Stopwatch.h"
|
||||
#include "Poco/Delegate.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
@ -79,6 +81,7 @@ using Poco::Data::AbstractExtractionVec;
|
|||
using Poco::Data::AbstractExtractionVecVec;
|
||||
using Poco::Data::AbstractBindingVec;
|
||||
using Poco::Data::NotConnectedException;
|
||||
using Poco::Data::SQLite::Notifier;
|
||||
using Poco::Nullable;
|
||||
using Poco::Tuple;
|
||||
using Poco::Any;
|
||||
|
@ -102,6 +105,7 @@ using Poco::Data::SQLite::ParameterCountMismatchException;
|
|||
using Poco::Int32;
|
||||
using Poco::Dynamic::Var;
|
||||
using Poco::Data::SQLite::Utility;
|
||||
using Poco::delegate;
|
||||
|
||||
|
||||
class Person
|
||||
|
@ -2765,6 +2769,7 @@ void SQLiteTest::testCommitCallback()
|
|||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
int age = 133132;
|
||||
int count = 0;
|
||||
std::string result;
|
||||
tmp.begin();
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
|
@ -2806,6 +2811,7 @@ void SQLiteTest::testRollbackCallback()
|
|||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
int age = 133132;
|
||||
int count = 0;
|
||||
std::string result;
|
||||
tmp.begin();
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
|
@ -2825,6 +2831,123 @@ void SQLiteTest::testRollbackCallback()
|
|||
}
|
||||
|
||||
|
||||
void SQLiteTest::testNotifier()
|
||||
{
|
||||
Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
assert (session.isConnected());
|
||||
session << "DROP TABLE IF EXISTS Person", now;
|
||||
session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
|
||||
Notifier notifier(session);
|
||||
notifier.insert += delegate(this, &SQLiteTest::onInsert);
|
||||
notifier.update += delegate(this, &SQLiteTest::onUpdate);
|
||||
notifier.erase += delegate(this, &SQLiteTest::onDelete);
|
||||
|
||||
_insertCounter = 0;
|
||||
_updateCounter = 0;
|
||||
_deleteCounter = 0;
|
||||
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Bart', 'Springfield', 12)", now;
|
||||
assert (_insertCounter == 1);
|
||||
assert (notifier.getRow() == 1);
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Lisa', 'Springfield', 10)", now;
|
||||
assert (_insertCounter == 2);
|
||||
assert (notifier.getRow() == 2);
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Homer', 'Springfield', 42)", now;
|
||||
assert (_insertCounter == 3);
|
||||
assert (notifier.getRow() == 3);
|
||||
|
||||
session << "UPDATE PERSON SET Age = 11 WHERE FirstName = 'Bart'", now;
|
||||
assert (_updateCounter == 1);
|
||||
assert (notifier.getRow() == 1);
|
||||
session << "UPDATE PERSON SET Age = 9 WHERE FirstName = 'Lisa'", now;
|
||||
assert (_updateCounter == 2);
|
||||
assert (notifier.getRow() == 2);
|
||||
session << "UPDATE PERSON SET Age = 41 WHERE FirstName = 'Homer'", now;
|
||||
assert (_updateCounter == 3);
|
||||
assert (notifier.getRow() == 3);
|
||||
|
||||
notifier.setRow(0);
|
||||
// SQLite optimizes DELETE so here we must have
|
||||
// the WHERE clause to trigger per-row notifications
|
||||
session << "DELETE FROM PERSON WHERE 1=1", now;
|
||||
assert (_deleteCounter == 3);
|
||||
assert (notifier.getRow() == 3);
|
||||
|
||||
notifier.insert -= delegate(this, &SQLiteTest::onInsert);
|
||||
notifier.update -= delegate(this, &SQLiteTest::onUpdate);
|
||||
notifier.erase -= delegate(this, &SQLiteTest::onDelete);
|
||||
|
||||
notifier.disableUpdate();
|
||||
|
||||
notifier.setRow(0);
|
||||
_commitCounter = 0;
|
||||
notifier.commit += delegate(this, &SQLiteTest::onCommit);
|
||||
session.begin();
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Bart', 'Springfield', 12)", now;
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Lisa', 'Springfield', 10)", now;
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Homer', 'Springfield', 42)", now;
|
||||
session.commit();
|
||||
assert (_commitCounter == 1);
|
||||
assert (notifier.getRow() == 0);
|
||||
notifier.commit -= delegate(this, &SQLiteTest::onCommit);
|
||||
|
||||
session << "DELETE FROM PERSON", now;
|
||||
|
||||
notifier.setRow(0);
|
||||
_rollbackCounter = 0;
|
||||
notifier.rollback += delegate(this, &SQLiteTest::onRollback);
|
||||
session.begin();
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Bart', 'Springfield', 12)", now;
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Lisa', 'Springfield', 10)", now;
|
||||
session << "INSERT INTO PERSON VALUES('Simpson', 'Homer', 'Springfield', 42)", now;
|
||||
session.rollback();
|
||||
assert (_rollbackCounter == 1);
|
||||
assert (notifier.getRow() == 0);
|
||||
notifier.rollback -= delegate(this, &SQLiteTest::onRollback);
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::onInsert(const void* pSender)
|
||||
{
|
||||
Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
|
||||
std::cout << "onInsert, row:" << pN->getRow() << std::endl;
|
||||
++_insertCounter;
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::onUpdate(const void* pSender)
|
||||
{
|
||||
Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
|
||||
std::cout << "onUpdate, row:" << pN->getRow() << std::endl;
|
||||
++_updateCounter;
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::onDelete(const void* pSender)
|
||||
{
|
||||
Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
|
||||
std::cout << "onDelete, row:" << pN->getRow() << std::endl;
|
||||
++_deleteCounter;
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::onCommit(const void* pSender)
|
||||
{
|
||||
Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
|
||||
std::cout << "onCommit, row:" << pN->getRow() << std::endl;
|
||||
++_commitCounter;
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::onRollback(const void* pSender)
|
||||
{
|
||||
Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
|
||||
std::cout << "onRollback, row:" << pN->getRow() << std::endl;
|
||||
++_rollbackCounter;
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::setTransactionIsolation(Session& session, Poco::UInt32 ti)
|
||||
{
|
||||
if (session.hasTransactionIsolation(ti))
|
||||
|
@ -3265,6 +3388,7 @@ CppUnit::Test* SQLiteTest::suite()
|
|||
CppUnit_addTest(pSuite, SQLiteTest, testUpdateCallback);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testCommitCallback);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testRollbackCallback);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testNotifier);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSessionTransaction);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTransaction);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTransactor);
|
||||
|
|
|
@ -146,6 +146,7 @@ public:
|
|||
void testUpdateCallback();
|
||||
void testCommitCallback();
|
||||
void testRollbackCallback();
|
||||
void testNotifier();
|
||||
|
||||
void testSessionTransaction();
|
||||
void testTransaction();
|
||||
|
@ -158,6 +159,12 @@ public:
|
|||
static int sqliteCommitCallbackFn(void*);
|
||||
static void sqliteRollbackCallbackFn(void*);
|
||||
|
||||
void onInsert(const void* pSender);
|
||||
void onUpdate(const void* pSender);
|
||||
void onDelete(const void* pSender);
|
||||
void onCommit(const void* pSender);
|
||||
void onRollback(const void* pSender);
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
|
@ -166,6 +173,9 @@ private:
|
|||
static int _insertCounter;
|
||||
static int _updateCounter;
|
||||
static int _deleteCounter;
|
||||
|
||||
int _commitCounter;
|
||||
int _rollbackCounter;
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче