aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/sqlite/sqlitesessionchangeset.cpp
diff options
context:
space:
mode:
authorMarco Bubke <[email protected]>2020-10-27 15:09:25 +0100
committerMarco Bubke <[email protected]>2020-11-03 09:19:54 +0000
commitc3873fcf40facd9cdf7ffc80a00f7112c3dbb8ce (patch)
tree1815d0075d9ebbd0e9ac11d1e9df0bac92494643 /src/libs/sqlite/sqlitesessionchangeset.cpp
parent3c7ab41e9efdb673d53572ab940fadc6cc68e984 (diff)
Sqlite: Add change set iterator
Task-number: QDS-2998 Change-Id: I7bfa8af51d9d7e6122902ee132ad51019e20afb5 Reviewed-by: Tim Jenssen <[email protected]> Reviewed-by: Thomas Hartmann <[email protected]>
Diffstat (limited to 'src/libs/sqlite/sqlitesessionchangeset.cpp')
-rw-r--r--src/libs/sqlite/sqlitesessionchangeset.cpp171
1 files changed, 163 insertions, 8 deletions
diff --git a/src/libs/sqlite/sqlitesessionchangeset.cpp b/src/libs/sqlite/sqlitesessionchangeset.cpp
index 430cbae222d..d348ac7bfce 100644
--- a/src/libs/sqlite/sqlitesessionchangeset.cpp
+++ b/src/libs/sqlite/sqlitesessionchangeset.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "sqlitesessionchangeset.h"
+#include "sqliteexception.h"
#include "sqlitesessions.h"
#include <utils/smallstringio.h>
@@ -33,7 +34,7 @@
namespace Sqlite {
namespace {
-void checkResultCode(int resultCode)
+void checkSessionChangeSetCreation(int resultCode)
{
switch (resultCode) {
case SQLITE_NOMEM:
@@ -44,29 +45,183 @@ void checkResultCode(int resultCode)
throw UnknowError("Unknow exception");
}
+void checkIteratorCreation(int resultCode)
+{
+ if (resultCode != SQLITE_OK)
+ throw Sqlite::CannotCreateChangeSetIterator{
+ "SessionChangeSet: Cannot create iterator from blob."};
+}
+
+void checkIteratorOperation(int resultCode)
+{
+ if (resultCode != SQLITE_OK)
+ throw Sqlite::CannotGetChangeSetOperation{
+ "SessionChangeSet: Cannot create iterator from blob."};
+}
+
+void checkChangeSetValue(int resultCode)
+{
+ switch (resultCode) {
+ case SQLITE_OK:
+ return;
+ case SQLITE_RANGE:
+ throw Sqlite::ChangeSetTupleIsOutOfRange{
+ "SessionChangeSet: You tried to access a non existing column."};
+ case SQLITE_MISUSE:
+ throw Sqlite::ChangeSetIsMisused{
+ "SessionChangeSet: Some misuse happened as you tried to access."};
+ }
+
+ throw Sqlite::UnknownError{"SessionChangeSet: Some unknown error happened."};
+}
+
+ValueView convertSqliteValue(sqlite3_value *value)
+{
+ if (value) {
+ int type = sqlite3_value_type(value);
+ switch (type) {
+ case SQLITE_INTEGER:
+ return ValueView::create(sqlite3_value_int64(value));
+ case SQLITE_FLOAT:
+ return ValueView::create(sqlite3_value_double(value));
+ case SQLITE_TEXT:
+ return ValueView::create(
+ Utils::SmallStringView{reinterpret_cast<const char *const>(sqlite3_value_text(value)),
+ static_cast<std::size_t>(sqlite3_value_bytes(value))});
+ case SQLITE_NULL:
+ return ValueView::create(NullValue{});
+ }
+ }
+
+ return ValueView::create(NullValue{});
+}
+
} // namespace
SessionChangeSet::SessionChangeSet(BlobView blob)
- : data(sqlite3_malloc64(blob.size()))
- , size(int(blob.size()))
+ : m_data(sqlite3_malloc64(blob.size()))
+ , m_size(int(blob.size()))
{
- std::memcpy(data, blob.data(), blob.size());
+ std::memcpy(m_data, blob.data(), blob.size());
}
SessionChangeSet::SessionChangeSet(Sessions &session)
{
- int resultCode = sqlite3session_changeset(session.session.get(), &size, &data);
- checkResultCode(resultCode);
+ int resultCode = sqlite3session_changeset(session.session.get(), &m_size, &m_data);
+ checkSessionChangeSetCreation(resultCode);
}
SessionChangeSet::~SessionChangeSet()
{
- sqlite3_free(data);
+ sqlite3_free(m_data);
}
BlobView SessionChangeSet::asBlobView() const
{
- return {static_cast<const byte *>(data), static_cast<std::size_t>(size)};
+ return {static_cast<const byte *>(m_data), static_cast<std::size_t>(m_size)};
+}
+
+SessionChangeSetInternal::ConstIterator SessionChangeSet::begin() const
+{
+ sqlite3_changeset_iter *sessionIterator;
+ int resultCode = sqlite3changeset_start(&sessionIterator, m_size, m_data);
+
+ checkIteratorCreation(resultCode);
+
+ SessionChangeSetInternal::ConstIterator iterator{sessionIterator};
+
+ ++iterator;
+
+ return iterator;
+}
+namespace SessionChangeSetInternal {
+ConstIterator::~ConstIterator()
+{
+ sqlite3changeset_finalize(m_sessionIterator);
+}
+
+namespace {
+State convertState(int state)
+{
+ switch (state) {
+ case SQLITE_ROW:
+ return State::Row;
+ case SQLITE_DONE:
+ return State::Done;
+ }
+
+ return State::Invalid;
+}
+
+Operation convertOperation(int operation)
+{
+ switch (operation) {
+ case SQLITE_INSERT:
+ return Operation::Insert;
+ case SQLITE_UPDATE:
+ return Operation::Update;
+ case SQLITE_DELETE:
+ return Operation::Delete;
+ }
+
+ return Operation::Invalid;
+}
+} // namespace
+
+ConstIterator &ConstIterator::operator++()
+{
+ int state = sqlite3changeset_next(m_sessionIterator);
+
+ m_state = convertState(state);
+
+ return *this;
+}
+
+Tuple ConstIterator::operator*() const
+{
+ const char *table;
+ int columnCount;
+ int operation;
+ int isIndirect;
+
+ int resultCode = sqlite3changeset_op(m_sessionIterator, &table, &columnCount, &operation, &isIndirect);
+
+ checkIteratorOperation(resultCode);
+
+ return {table, m_sessionIterator, columnCount, convertOperation(operation)};
+}
+
+namespace {
+ValueViews fetchValues(sqlite3_changeset_iter *sessionIterator, int column, Operation operation)
+{
+ sqlite3_value *newValue = nullptr;
+
+ if (operation == Operation::Insert || operation == Operation::Update) {
+ int resultCode = sqlite3changeset_new(sessionIterator, column, &newValue);
+
+ checkChangeSetValue(resultCode);
+ }
+
+ sqlite3_value *oldValue = nullptr;
+ if (operation == Operation::Delete || operation == Operation::Update) {
+ int resultCode = sqlite3changeset_old(sessionIterator, column, &oldValue);
+
+ checkChangeSetValue(resultCode);
+ }
+
+ return {convertSqliteValue(newValue), convertSqliteValue(oldValue)};
+}
+} // namespace
+
+ValueViews ConstTupleIterator::operator*() const
+{
+ return fetchValues(m_sessionIterator, m_column, m_operation);
+}
+
+ValueViews Tuple::operator[](int column) const
+{
+ return fetchValues(sessionIterator, column, operation);
}
+} // namespace SessionChangeSetInternal
} // namespace Sqlite