summaryrefslogtreecommitdiff
path: root/sqlitebackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sqlitebackend.cpp')
-rw-r--r--sqlitebackend.cpp260
1 files changed, 150 insertions, 110 deletions
diff --git a/sqlitebackend.cpp b/sqlitebackend.cpp
index b95e18d..434f1e6 100644
--- a/sqlitebackend.cpp
+++ b/sqlitebackend.cpp
@@ -4,64 +4,102 @@
#include "sqlitebackend.h"
-SQLiteSaveFile::SQLiteSaveFile(QObject *parent, QString filename) :
+SQLiteSaveFile::SQLiteSaveFile(QObject *parent) :
QObject(parent)
- , lastError(NoError)
- , lastErrorString(QString())
- , db(QSqlDatabase::addDatabase("QSQLITE", QUuid::createUuid().toString()))
- , filename(filename)
- , m_isOpen(false)
+ , m_lastError(NoError)
+ , m_lastErrorString(QString())
+ , m_open(false)
+ , m_dirty(false)
{
- connect();
+ clearNew();
}
-bool SQLiteSaveFile::initDb(bool setCreationDate)
+bool SQLiteSaveFile::open(const QString &filename)
{
- for (auto const &q: {
- "CREATE TABLE IF NOT EXISTS metadata (key TEXT, value TEXT)",
- "CREATE TABLE IF NOT EXISTS tags (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, anchor_x REAL, anchor_y REAL, meta TEXT)",
- "CREATE TABLE IF NOT EXISTS blobs (name TEXT, data BLOB)"}) {
- if (!runSql(q))
+ qDebug() << "open";
+ {
+ QMutexLocker l(&m_dbMut);
+ QFile f(filename);
+ if (!f.exists()) {
+ setError(FileNotFoundError, QString("File \"%1\"does not exist.").arg(filename));
return false;
- }
+ }
- if (setCreationDate) {
- if (!setMetaLocked("creationTime", QDateTime::currentDateTimeUtc().toMSecsSinceEpoch()))
+ QSqlDatabase new_db(QSqlDatabase::addDatabase("QSQLITE", QUuid::createUuid().toString()));
+ new_db.setDatabaseName(f.fileName());
+ if (!new_db.open()) {
+ setDatabaseError(new_db);
+ new_db.close();
return false;
+ }
+
+ m_db.close();
+ m_db = new_db;
+
+ /* Try to load image, ignore if image is unset */
+ QSqlQuery q("SELECT data FROM blobs WHERE name = 'image'", m_db);
+ if (!q.exec())
+ return setDatabaseError(q);
+ if (!q.next())
+ return setDatabaseError(q);
+
+ m_memory = false;
+ m_dirty = false;
+ m_open = true;
+ m_image = q.value(0).toByteArray();
}
-
+ fileReload(); /* Call after unlocking mutex to allow accesses by receivers */
return true;
}
-bool SQLiteSaveFile::connect()
+bool SQLiteSaveFile::clearNew()
{
- QMutexLocker l(&dbMut);
- resetError();
- m_isOpen = false;
- imageData = QByteArray();
+ qDebug() << "clearNew";
+ {
+ QMutexLocker l(&m_dbMut);
+
+ QSqlDatabase new_db(QSqlDatabase::addDatabase("QSQLITE", QUuid::createUuid().toString()));
+ new_db.setDatabaseName(":memory:");
+ if (!new_db.open()) {
+ setDatabaseError(new_db);
+ new_db.close();
+ return false;
+ }
- bool newlyCreated = QFile(filename).exists();
+ QSqlDatabase old_db = m_db;
+ m_db = new_db;
- db.setDatabaseName(filename);
- if (!db.open()) {
- setDatabaseError(db);
- db.close();
- return false;
- }
+ if (!initDb(true)) {
+ m_db.close();
+ m_db = old_db;
+ return false;
+ }
- if (!initDb(newlyCreated)) {
- db.close();
- return false;
+ old_db.close();
+ m_memory = true;
+ m_dirty = false;
+ m_open = true;
+ m_image = QByteArray();
}
+ fileReload(); /* Call after unlocking mutex to allow accesses by receivers */
+ return true;
+}
- m_isOpen = true;
+bool SQLiteSaveFile::initDb(bool setCreationDate)
+{
+ for (auto const &q: {
+ "CREATE TABLE IF NOT EXISTS metadata (key TEXT, value TEXT)",
+ "CREATE TABLE IF NOT EXISTS tags (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, anchor_x REAL, anchor_y REAL, meta TEXT)",
+ "CREATE TABLE IF NOT EXISTS blobs (name TEXT, data BLOB)"}) {
+ if (!runSql(q))
+ return false;
+ }
- /* Try to load image, ignore if image is unset */
- QSqlQuery q("SELECT data FROM blobs WHERE name = 'image'", db);
- if (!q.next())
- return setDatabaseError(q);
+ if (setCreationDate) {
+ if (!setMetaLocked("creationTime", QDateTime::currentDateTimeUtc().toMSecsSinceEpoch()))
+ return false;
+ }
- imageData = q.value(0).toByteArray();
return true;
}
@@ -74,66 +112,50 @@ static sqlite3 *getSqliteHandle(QSqlDatabase &db) {
bool SQLiteSaveFile::saveAs(const QString &filename)
{
- QMutexLocker l(&dbMut);
+ qDebug() << "saveAs" << filename;
+ QMutexLocker l(&m_dbMut);
QFile f(filename);
- QSqlDatabase old_db = db;
QSqlDatabase new_db(QSqlDatabase::addDatabase("QSQLITE", QUuid::createUuid().toString()));
- new_db.setDatabaseName(f.fileName());
- if (!new_db.open()) {
- setDatabaseError(new_db);
- new_db.close();
- return false;
+ {
+ new_db.setDatabaseName(f.fileName());
+ if (!new_db.open())
+ goto err_cleanup;
+
+ sqlite3 *old_handle = getSqliteHandle(m_db);
+ sqlite3 *new_handle = getSqliteHandle(new_db);
+ sqlite3_backup *bck = sqlite3_backup_init(new_handle, "main", old_handle, "main");
+ if (!bck)
+ goto err_cleanup;
+
+ if (sqlite3_backup_step(bck, -1) != SQLITE_DONE)
+ goto err_cleanup;
+
+ if (sqlite3_backup_finish(bck) != SQLITE_DONE)
+ goto err_cleanup;
+
+ m_db.close();
+ m_db = new_db;
+ m_memory = false;
+ return true;
}
-
- sqlite3 *old_handle = getSqliteHandle(db);
- sqlite3 *new_handle = getSqliteHandle(new_db);
- sqlite3_backup *bck = sqlite3_backup_init(new_handle, "main", old_handle, "main");
- if (!bck)
- goto err_cleanup;
-
- if (sqlite3_backup_step(bck, -1) != SQLITE_DONE)
- goto err_cleanup;
-
- if (sqlite3_backup_finish(bck) != SQLITE_DONE)
- goto err_cleanup;
-
- db = new_db;
- old_db.close();
- return true;
-
err_cleanup:
setDatabaseError(new_db);
new_db.close();
return false;
}
-bool SQLiteSaveFile::clearNew()
-{
- QMutexLocker l(&dbMut);
-
- QSqlDatabase new_db(QSqlDatabase::addDatabase("QSQLITE", QUuid::createUuid().toString()));
- new_db.setDatabaseName(":memory:");
- if (!new_db.open()) {
- setDatabaseError(new_db);
- new_db.close();
- return false;
- }
-
- if (!initDb()) {
- db.close();
- return false;
- }
-
- imageData = QByteArray();
- return true;
-}
-
QList<Tag> SQLiteSaveFile::getAllTags()
{
- QMutexLocker l(&dbMut);
+ qDebug() << "getAllTags";
+ QMutexLocker l(&m_dbMut);
resetError();
QList<Tag> rv;
- QSqlQuery q("SELECT (id, name, anchor_x, anchor_y, meta) FROM tags", db);
+
+ QSqlQuery q("SELECT id, name, anchor_x, anchor_y, meta FROM tags", m_db);
+ if (!q.exec()) {
+ setDatabaseError(q);
+ return QList<Tag>();
+ }
while (q.next()) {
rv << Tag {
@@ -153,39 +175,44 @@ QList<Tag> SQLiteSaveFile::getAllTags()
bool SQLiteSaveFile::updateTag(Tag tag)
{
- QMutexLocker l(&dbMut);
+ QMutexLocker l(&m_dbMut);
if (!runSql("UPDATE tags SET name=?, anchor_x=?, anchor_y=?, meta=? WHERE id=?", {
tag.name, tag.anchor.x(), tag.anchor.y(), QJsonDocument::fromVariant(tag.metadata).toJson(), tag.id
}))
return false;
+ m_dirty = true;
tagChange(TagChange::CHANGED, tag);
return true;
}
bool SQLiteSaveFile::deleteTag(Tag tag)
{
- QMutexLocker l(&dbMut);
+ QMutexLocker l(&m_dbMut);
if (!runSql("DELETE FROM tags WHERE id=?", {tag.id}))
return false;
+ m_dirty = true;
tagChange(TagChange::DELETED, tag);
return true;
}
bool SQLiteSaveFile::createTag(Tag tag)
{
- QMutexLocker l(&dbMut);
+ qDebug() << "createTag";
+ QMutexLocker l(&m_dbMut);
resetError();
- QSqlQuery q("INSERT INTO tags(name, anchor_x, anchor_y, meta) VALUES (?, ?, ?, ?)", db);
+ QSqlQuery q("INSERT INTO tags(name, anchor_x, anchor_y, meta) VALUES (?, ?, ?, ?)", m_db);
q.addBindValue(tag.name);
q.addBindValue(tag.anchor.x());
q.addBindValue(tag.anchor.y());
q.addBindValue(QJsonDocument::fromVariant(tag.metadata).toJson());
+
if (!q.exec())
return setDatabaseError(q);
Tag created_tag(q.lastInsertId().toLongLong(), tag);
+ m_dirty = true;
tagChange(TagChange::CREATED, created_tag);
return true;
}
@@ -205,25 +232,34 @@ bool SQLiteSaveFile::setMetaLocked(std::initializer_list<QPair<QString, QVariant
}
bool SQLiteSaveFile::setMeta(const QString &key, const QVariant &value) {
- QMutexLocker l(&dbMut);
+ QMutexLocker l(&m_dbMut);
+ m_dirty = true;
return setMetaLocked(key, value);
}
bool SQLiteSaveFile::setMeta(std::initializer_list<QPair<QString, QVariant>> metas) {
- QMutexLocker l(&dbMut);
+ QMutexLocker l(&m_dbMut);
+ m_dirty = true;
return setMetaLocked(metas);
}
-QVariant SQLiteSaveFile::getMeta(const QString &key) {
- QMutexLocker l(&dbMut);
+const QVariant SQLiteSaveFile::getMeta(const QString &key) const {
+ QMutexLocker l(&m_dbMut);
return getMetaLocked(key);
}
-QVariant SQLiteSaveFile::getMetaLocked(const QString &key)
+const QVariant SQLiteSaveFile::getMetaLocked(const QString &key) const
{
+ qDebug() << "getMeta " << key;
resetError();
- QSqlQuery q("SELECT value FROM metadata WHERE key=?", db);
+ QSqlQuery q("SELECT value FROM metadata WHERE key=?", m_db);
q.addBindValue(key);
+
+ if (!q.exec()) {
+ setDatabaseError(q);
+ return QVariant();
+ }
+
if (!q.next()) {
setDatabaseError(q);
return QVariant();
@@ -234,18 +270,22 @@ QVariant SQLiteSaveFile::getMetaLocked(const QString &key)
bool SQLiteSaveFile::runSql(QString query, std::initializer_list<QVariant> bindings)
{
+ qDebug() << "runSql " << query;
resetError();
- QSqlQuery q(query, db);
- for (const QVariant &v : bindings)
+ QSqlQuery q(query, m_db);
+ for (const QVariant &v : bindings) {
q.addBindValue(v);
+ }
- q.exec();
- return setDatabaseError(q);
+ if (!q.exec()) {
+ return setDatabaseError(q);
+ }
+ return true;
}
bool SQLiteSaveFile::loadImageFromDisk(const QString &filename)
{
- QMutexLocker l(&dbMut);
+ QMutexLocker l(&m_dbMut);
QFile f(filename);
resetError();
@@ -254,7 +294,7 @@ bool SQLiteSaveFile::loadImageFromDisk(const QString &filename)
return false;
}
- imageData = f.readAll();
+ m_image = f.readAll();
if (f.error() != QFileDevice::NoError) {
setError(ImageReadError, QString("Failed to read image: %1").arg(f.errorString()));
return false;
@@ -266,7 +306,8 @@ bool SQLiteSaveFile::loadImageFromDisk(const QString &filename)
{"imageLoadedTime", QDateTime::currentDateTimeUtc().toMSecsSinceEpoch()}}))
return false;
- return runSql("INSERT OR REPLACE INTO blobs(name, data) VALUES ('image', ?)", {imageData});
+ m_dirty = true;
+ return runSql("INSERT OR REPLACE INTO blobs(name, data) VALUES ('image', ?)", {m_image});
}
bool SQLiteSaveFile::reloadImageFromDisk()
@@ -287,11 +328,7 @@ Tag::Tag(long long id, QString name, qreal anchor_x, qreal anchor_y, QByteArray
, name(name)
, anchor(QPointF(anchor_x, anchor_y))
, metadata(QJsonDocument::fromJson(metadata).object().toVariantMap())
-{
-}
-
-Tag::Tag()
- : id(-1)
+ , valid(true)
{
}
@@ -300,23 +337,26 @@ Tag::Tag(long long id, const Tag &other)
, name(other.name)
, anchor(other.anchor)
, metadata(other.metadata)
+ , valid(true)
{
}
-bool SQLiteSaveFile::setDatabaseError(const QSqlQuery &q)
+bool SQLiteSaveFile::setDatabaseError(const QSqlQuery &q) const
{
if (!q.lastError().isValid())
return true;
- setError(SQLiteError, QString("Project file database error: %1").arg(q.lastError().text()));
+ qDebug() << "Query error: " << q.lastError().text();
+ setError(SQLiteError, QString("Project file database error executing %1: %2").arg(q.executedQuery()).arg(q.lastError().text()));
return false;
}
-bool SQLiteSaveFile::setDatabaseError(const QSqlDatabase &db)
+bool SQLiteSaveFile::setDatabaseError(const QSqlDatabase &db) const
{
if (!db.lastError().isValid())
return true;
+ qDebug() << "Database error: " << db.lastError().text();
setError(SQLiteError, QString("Project file database error: %1").arg(db.lastError().text()));
return false;
}