forked from qt-creator/qt-creator
Sqlite: Add update hook and use it to get the last changed id
Sqlite has a function to get the last inserted rowid but very often you want to get the updated rowid too. Change-Id: Ie276a5039682813ad16597433996a2959f54d9ba Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
71
src/libs/sqlite/lastchangedrowid.h
Normal file
71
src/libs/sqlite/lastchangedrowid.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sqlitedatabaseinterface.h"
|
||||
|
||||
#include <utils/smallstringio.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
class LastChangedRowId
|
||||
{
|
||||
public:
|
||||
LastChangedRowId(DatabaseInterface &database,
|
||||
Utils::SmallStringView databaseName,
|
||||
Utils::SmallStringView tableName)
|
||||
: database(database)
|
||||
, databaseName(databaseName)
|
||||
, tableName(tableName)
|
||||
{
|
||||
callback = [this](ChangeType, char const *database, char const *table, long long rowId) {
|
||||
if (this->databaseName == database && this->tableName == table)
|
||||
lastRowId = rowId;
|
||||
};
|
||||
|
||||
database.setUpdateHook(callback);
|
||||
}
|
||||
|
||||
~LastChangedRowId() { database.resetUpdateHook(); }
|
||||
|
||||
long long takeLastRowId()
|
||||
{
|
||||
long long rowId = lastRowId;
|
||||
lastRowId = -1;
|
||||
return rowId;
|
||||
}
|
||||
|
||||
public:
|
||||
DatabaseInterface &database;
|
||||
DatabaseInterface::UpdateCallback callback;
|
||||
Utils::SmallStringView databaseName;
|
||||
Utils::SmallStringView tableName;
|
||||
long long lastRowId = -1;
|
||||
};
|
||||
|
||||
} // namespace Sqlite
|
||||
@@ -25,6 +25,7 @@ SOURCES += \
|
||||
$$PWD/sqlitebasestatement.cpp
|
||||
HEADERS += \
|
||||
$$PWD/createtablesqlstatementbuilder.h \
|
||||
$$PWD/lastchangedrowid.h \
|
||||
$$PWD/sqlitedatabasebackend.h \
|
||||
$$PWD/sqlitedatabaseinterface.h \
|
||||
$$PWD/sqliteexception.h \
|
||||
|
||||
@@ -114,6 +114,13 @@ public:
|
||||
m_databaseBackend.walCheckpointFull();
|
||||
}
|
||||
|
||||
void setUpdateHook(DatabaseBackend::UpdateCallback &callback)
|
||||
{
|
||||
m_databaseBackend.setUpdateHook(callback);
|
||||
}
|
||||
|
||||
void resetUpdateHook() { m_databaseBackend.resetUpdateHook(); }
|
||||
|
||||
private:
|
||||
void deferredBegin() override;
|
||||
void immediateBegin() override;
|
||||
|
||||
@@ -344,13 +344,11 @@ int indexOfPragma(Utils::SmallStringView pragma, const Utils::SmallStringView (&
|
||||
}
|
||||
}
|
||||
|
||||
constexpr const Utils::SmallStringView journalModeStrings[] = {
|
||||
"delete",
|
||||
"truncate",
|
||||
"persist",
|
||||
"memory",
|
||||
"wal"
|
||||
};
|
||||
const Utils::SmallStringView journalModeStrings[] = {"delete",
|
||||
"truncate",
|
||||
"persist",
|
||||
"memory",
|
||||
"wal"};
|
||||
|
||||
Utils::SmallStringView DatabaseBackend::journalModeToPragma(JournalMode journalMode)
|
||||
{
|
||||
@@ -367,11 +365,7 @@ JournalMode DatabaseBackend::pragmaToJournalMode(Utils::SmallStringView pragma)
|
||||
return static_cast<JournalMode>(index);
|
||||
}
|
||||
|
||||
constexpr const Utils::SmallStringView textEncodingStrings[] = {
|
||||
"UTF-8",
|
||||
"UTF-16le",
|
||||
"UTF-16be"
|
||||
};
|
||||
const Utils::SmallStringView textEncodingStrings[] = {"UTF-8", "UTF-16le", "UTF-16be"};
|
||||
|
||||
Utils::SmallStringView DatabaseBackend::textEncodingToPragma(TextEncoding textEncoding)
|
||||
{
|
||||
@@ -426,6 +420,29 @@ void DatabaseBackend::walCheckpointFull()
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void updateCallback(
|
||||
void *callback, int type, char const *database, char const *table, sqlite3_int64 row)
|
||||
{
|
||||
auto &function = *reinterpret_cast<DatabaseBackend::UpdateCallback *>(callback);
|
||||
|
||||
function(static_cast<ChangeType>(type), database, table, row);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void DatabaseBackend::setUpdateHook(UpdateCallback &callback)
|
||||
{
|
||||
if (callback)
|
||||
sqlite3_update_hook(m_databaseHandle, updateCallback, &callback);
|
||||
else
|
||||
sqlite3_update_hook(m_databaseHandle, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void DatabaseBackend::resetUpdateHook()
|
||||
{
|
||||
sqlite3_update_hook(m_databaseHandle, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void DatabaseBackend::throwExceptionStatic(const char *whatHasHappens)
|
||||
{
|
||||
throw Exception(whatHasHappens);
|
||||
|
||||
@@ -40,6 +40,9 @@ class Database;
|
||||
class SQLITE_EXPORT DatabaseBackend
|
||||
{
|
||||
public:
|
||||
using UpdateCallback
|
||||
= std::function<void(ChangeType type, char const *, char const *, long long)>;
|
||||
|
||||
DatabaseBackend(Database &database);
|
||||
~DatabaseBackend();
|
||||
|
||||
@@ -87,6 +90,9 @@ public:
|
||||
|
||||
void walCheckpointFull();
|
||||
|
||||
void setUpdateHook(UpdateCallback &callback);
|
||||
void resetUpdateHook();
|
||||
|
||||
protected:
|
||||
bool databaseIsOpen() const;
|
||||
|
||||
@@ -128,7 +134,6 @@ private:
|
||||
Database &m_database;
|
||||
sqlite3 *m_databaseHandle;
|
||||
TextEncoding m_cachedTextEncoding;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Sqlite
|
||||
|
||||
@@ -25,11 +25,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/smallstringview.h>
|
||||
|
||||
#include "sqliteglobal.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Sqlite {
|
||||
class DatabaseInterface
|
||||
{
|
||||
public:
|
||||
using UpdateCallback
|
||||
= std::function<void(ChangeType type, char const *, char const *, long long)>;
|
||||
|
||||
virtual void walCheckpointFull() = 0;
|
||||
virtual void execute(Utils::SmallStringView sqlStatement) = 0;
|
||||
virtual void setUpdateHook(UpdateCallback &callback) = 0;
|
||||
virtual void resetUpdateHook() = 0;
|
||||
|
||||
protected:
|
||||
~DatabaseInterface() = default;
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
class SQLITE_EXPORT Exception
|
||||
|
||||
@@ -84,4 +84,6 @@ enum TextEncoding : char
|
||||
|
||||
};
|
||||
|
||||
enum class ChangeType : int { Delete = 9, Insert = 18, Update = 23 };
|
||||
|
||||
} // namespace Sqlite
|
||||
|
||||
Reference in New Issue
Block a user