diff options
| author | Marco Bubke <[email protected]> | 2020-10-27 15:09:25 +0100 |
|---|---|---|
| committer | Marco Bubke <[email protected]> | 2020-11-03 09:19:54 +0000 |
| commit | c3873fcf40facd9cdf7ffc80a00f7112c3dbb8ce (patch) | |
| tree | 1815d0075d9ebbd0e9ac11d1e9df0bac92494643 /src/libs/sqlite/sqlitesessionchangeset.cpp | |
| parent | 3c7ab41e9efdb673d53572ab940fadc6cc68e984 (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.cpp | 171 |
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 |
