Move sqlite database open/close to a new SQLiteDatabase.
authorCarl Hetherington <cth@carlh.net>
Sat, 18 Jan 2025 23:21:11 +0000 (00:21 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 22 Jan 2025 13:34:25 +0000 (14:34 +0100)
13 files changed:
src/lib/cinema_list.cc
src/lib/cinema_list.h
src/lib/dkdm_recipient_list.cc
src/lib/dkdm_recipient_list.h
src/lib/exceptions.cc
src/lib/exceptions.h
src/lib/sqlite_database.cc [new file with mode: 0644]
src/lib/sqlite_database.h [new file with mode: 0644]
src/lib/sqlite_statement.cc
src/lib/sqlite_statement.h
src/lib/sqlite_transaction.cc
src/lib/sqlite_transaction.h
src/lib/wscript

index e4095f1c4eb08b13540159db9abbfb6600a2049f..4ee538efe442f54f1834e56c756cfe73e04f66fd 100644 (file)
@@ -47,9 +47,10 @@ CinemaList::CinemaList()
        : _cinemas("cinemas")
        , _screens("screens")
        , _trusted_devices("trusted_devices")
+       , _db(Config::instance()->cinemas_file())
 {
        setup_tables();
-       setup(Config::instance()->cinemas_file());
+       setup();
 }
 
 
@@ -57,9 +58,10 @@ CinemaList::CinemaList(boost::filesystem::path db_file)
        : _cinemas("cinemas")
        , _screens("screens")
        , _trusted_devices("trusted_devices")
+       , _db(db_file)
 {
        setup_tables();
-       setup(db_file);
+       setup();
 }
 
 
@@ -161,19 +163,8 @@ CinemaList::clear()
 
 
 void
-CinemaList::setup(boost::filesystem::path db_file)
+CinemaList::setup()
 {
-#ifdef DCPOMATIC_WINDOWS
-       auto rc = sqlite3_open16(db_file.c_str(), &_db);
-#else
-       auto rc = sqlite3_open(db_file.c_str(), &_db);
-#endif
-       if (rc != SQLITE_OK) {
-               throw FileError("Could not open SQLite database", db_file);
-       }
-
-       sqlite3_busy_timeout(_db, 500);
-
        SQLiteStatement cinemas(_db, _cinemas.create());
        cinemas.execute();
 
@@ -185,27 +176,6 @@ CinemaList::setup(boost::filesystem::path db_file)
 }
 
 
-CinemaList::CinemaList(CinemaList&& other)
-       : _db(other._db)
-       , _cinemas(std::move(other._cinemas))
-       , _screens(std::move(other._screens))
-       , _trusted_devices(std::move(other._trusted_devices))
-{
-       other._db = nullptr;
-}
-
-
-CinemaList&
-CinemaList::operator=(CinemaList&& other)
-{
-       if (this != &other) {
-               _db = other._db;
-               other._db = nullptr;
-       }
-       return *this;
-}
-
-
 CinemaID
 CinemaList::add_cinema(Cinema const& cinema)
 {
@@ -219,7 +189,7 @@ CinemaList::add_cinema(Cinema const& cinema)
 
        statement.execute();
 
-       return sqlite3_last_insert_rowid(_db);
+       return sqlite3_last_insert_rowid(_db.db());
 }
 
 
@@ -248,14 +218,6 @@ CinemaList::remove_cinema(CinemaID id)
 }
 
 
-CinemaList::~CinemaList()
-{
-       if (_db) {
-               sqlite3_close(_db);
-       }
-}
-
-
 static
 vector<pair<CinemaID, Cinema>>
 cinemas_from_result(SQLiteStatement& statement)
@@ -314,7 +276,7 @@ CinemaList::add_screen(CinemaID cinema_id, dcpomatic::Screen const& screen)
 
        add_screen.execute();
 
-       auto const screen_id = sqlite3_last_insert_rowid(_db);
+       auto const screen_id = sqlite3_last_insert_rowid(_db.db());
 
        for (auto device: screen.trusted_devices) {
                SQLiteStatement add_device(_db, _trusted_devices.insert());
index 1e0144f73320e18801792959086b7a3a0c2cee9b..40e32410fa9c21001e4ddab766908194f1a01cc5 100644 (file)
@@ -24,6 +24,7 @@
 
 
 #include "id.h"
+#include "sqlite_database.h"
 #include "sqlite_table.h"
 #include <libcxml/cxml.h>
 #include <dcp/utc_offset.h>
@@ -77,14 +78,10 @@ class CinemaList
 public:
        CinemaList();
        CinemaList(boost::filesystem::path db_file);
-       ~CinemaList();
 
        CinemaList(CinemaList const&) = delete;
        CinemaList& operator=(CinemaList const&) = delete;
 
-       CinemaList(CinemaList&& other);
-       CinemaList& operator=(CinemaList&& other);
-
        void read_legacy_file(boost::filesystem::path xml_file);
        void read_legacy_string(std::string const& xml);
 
@@ -117,13 +114,13 @@ private:
        dcpomatic::Screen screen_from_result(SQLiteStatement& statement, ScreenID screen_id, bool with_trusted_devices) const;
        std::vector<std::pair<ScreenID, dcpomatic::Screen>> screens_from_result(SQLiteStatement& statement) const;
        void setup_tables();
-       void setup(boost::filesystem::path db_file);
+       void setup();
        void read_legacy_document(cxml::Document const& doc);
 
-       sqlite3* _db = nullptr;
        SQLiteTable _cinemas;
        SQLiteTable _screens;
        SQLiteTable _trusted_devices;
+       mutable SQLiteDatabase _db;
 };
 
 
index f67379122dd9155eabd64a12548c5a57d2bbf90d..c57ade437df120a7c171312a44ceaef218b609c3 100644 (file)
@@ -37,27 +37,21 @@ using boost::optional;
 
 DKDMRecipientList::DKDMRecipientList()
        : _dkdm_recipients("dkdm_recipients")
+       , _db(Config::instance()->dkdm_recipients_file())
 {
-       setup(Config::instance()->dkdm_recipients_file());
+       setup();
 }
 
 
 DKDMRecipientList::DKDMRecipientList(boost::filesystem::path db_file)
        : _dkdm_recipients("dkdm_recipients")
+       , _db(db_file)
 {
-       setup(db_file);
+       setup();
 }
 
 
 
-DKDMRecipientList::~DKDMRecipientList()
-{
-       if (_db) {
-               sqlite3_close(_db);
-       }
-}
-
-
 void
 DKDMRecipientList::read_legacy_file(boost::filesystem::path xml_file)
 {
@@ -105,48 +99,18 @@ DKDMRecipientList::read_legacy_document(cxml::Document const& doc)
 
 
 void
-DKDMRecipientList::setup(boost::filesystem::path db_file)
+DKDMRecipientList::setup()
 {
        _dkdm_recipients.add_column("name", "TEXT");
        _dkdm_recipients.add_column("notes", "TEXT");
        _dkdm_recipients.add_column("recipient", "TEXT");
        _dkdm_recipients.add_column("emails", "TEXT");
 
-#ifdef DCPOMATIC_WINDOWS
-       auto rc = sqlite3_open16(db_file.c_str(), &_db);
-#else
-       auto rc = sqlite3_open(db_file.c_str(), &_db);
-#endif
-       if (rc != SQLITE_OK) {
-               throw FileError("Could not open SQLite database", db_file);
-       }
-
-       sqlite3_busy_timeout(_db, 500);
-
        SQLiteStatement screens(_db, _dkdm_recipients.create());
        screens.execute();
 }
 
 
-DKDMRecipientList::DKDMRecipientList(DKDMRecipientList&& other)
-       : _dkdm_recipients(std::move(other._dkdm_recipients))
-{
-       _db = other._db;
-       other._db = nullptr;
-}
-
-
-DKDMRecipientList&
-DKDMRecipientList::operator=(DKDMRecipientList&& other)
-{
-       if (this != &other) {
-               _db = other._db;
-               other._db = nullptr;
-       }
-       return *this;
-}
-
-
 DKDMRecipientID
 DKDMRecipientList::add_dkdm_recipient(DKDMRecipient const& dkdm_recipient)
 {
@@ -159,7 +123,7 @@ DKDMRecipientList::add_dkdm_recipient(DKDMRecipient const& dkdm_recipient)
 
        add_dkdm_recipient.execute();
 
-       return sqlite3_last_insert_rowid(_db);
+       return sqlite3_last_insert_rowid(_db.db());
 }
 
 
index fc4d84b60c3ef9ec5bee51757c1e0259e7abc2e8..3847239b58f36634bd093b5276ee3b0457891954 100644 (file)
@@ -24,6 +24,7 @@
 
 
 #include "id.h"
+#include "sqlite_database.h"
 #include "sqlite_table.h"
 #include <libcxml/cxml.h>
 #include <boost/filesystem.hpp>
@@ -58,14 +59,10 @@ class DKDMRecipientList
 public:
        DKDMRecipientList();
        DKDMRecipientList(boost::filesystem::path db_file);
-       ~DKDMRecipientList();
 
        DKDMRecipientList(DKDMRecipientList const&) = delete;
        DKDMRecipientList& operator=(DKDMRecipientList const&) = delete;
 
-       DKDMRecipientList(DKDMRecipientList&& other);
-       DKDMRecipientList& operator=(DKDMRecipientList&& other);
-
        void read_legacy_file(boost::filesystem::path xml_file);
        void read_legacy_string(std::string const& xml);
 
@@ -78,11 +75,11 @@ public:
        boost::optional<DKDMRecipient> dkdm_recipient(DKDMRecipientID id) const;
 
 private:
-       void setup(boost::filesystem::path db_file);
+       void setup();
        void read_legacy_document(cxml::Document const& doc);
 
-       sqlite3* _db = nullptr;
        SQLiteTable _dkdm_recipients;
+       mutable SQLiteDatabase _db;
 };
 
 
index 27496dcdcd5fe3d26995919c4d3e22f65678f87d..5f0fe935a1ddf70b77ae1b76681c1d84a1818fa3 100644 (file)
@@ -19,8 +19,9 @@
 */
 
 
-#include "exceptions.h"
 #include "compose.hpp"
+#include "exceptions.h"
+#include "sqlite_database.h"
 
 #include "i18n.h"
 
@@ -180,3 +181,13 @@ DiskFullError::DiskFullError(boost::filesystem::path writing)
 
 }
 
+
+boost::filesystem::path
+SQLError::get_filename(SQLiteDatabase& db)
+{
+       if (auto filename = sqlite3_db_filename(db.db(), "main")) {
+               return filename;
+       }
+
+       return {};
+}
index c1bb8f6b6c3680713872a47d3db29c12e779cdca..dae64fb5d1d6ca304b4b08f3546bb94e32e547b7 100644 (file)
@@ -39,6 +39,9 @@ extern "C" {
 #include <stdexcept>
 
 
+class SQLiteDatabase;
+
+
 /** @class DecodeError
  *  @brief A low-level problem with the decoder (possibly due to the nature
  *  of a source file).
@@ -484,19 +487,19 @@ public:
 class SQLError : public std::runtime_error
 {
 public:
-       SQLError(sqlite3* db, char const* s)
+       SQLError(SQLiteDatabase& db, char const* s)
                : std::runtime_error(get_message(db, s))
        {
                _filename = get_filename(db);
        }
 
-       SQLError(sqlite3* db, int rc)
+       SQLError(SQLiteDatabase& db, int rc)
                : std::runtime_error(get_message(db, rc))
        {
                _filename = get_filename(db);
        }
 
-       SQLError(sqlite3* db, int rc, std::string doing)
+       SQLError(SQLiteDatabase& db, int rc, std::string doing)
                : std::runtime_error(get_message(db, rc, doing))
        {
                _filename = get_filename(db);
@@ -507,26 +510,19 @@ public:
        }
 
 private:
-       boost::filesystem::path get_filename(sqlite3* db)
-       {
-               if (auto filename = sqlite3_db_filename(db, "main")) {
-                       return filename;
-               }
-
-               return {};
-       }
+       boost::filesystem::path get_filename(SQLiteDatabase& db);
 
-       std::string get_message(sqlite3* db, char const* s)
+       std::string get_message(SQLiteDatabase& db, char const* s)
        {
                return String::compose("%1 (in %2)", s, get_filename(db));
        }
 
-       std::string get_message(sqlite3* db, int rc)
+       std::string get_message(SQLiteDatabase& db, int rc)
        {
                return String::compose("%1 (in %2)", sqlite3_errstr(rc), get_filename(db));
        }
 
-       std::string get_message(sqlite3* db, int rc, std::string doing)
+       std::string get_message(SQLiteDatabase& db, int rc, std::string doing)
        {
                return String::compose("%1 (while doing %2) (in %3)", sqlite3_errstr(rc), doing, get_filename(db));
        }
diff --git a/src/lib/sqlite_database.cc b/src/lib/sqlite_database.cc
new file mode 100644 (file)
index 0000000..f027012
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+    Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "exceptions.h"
+#include "sqlite_database.h"
+#include <sqlite3.h>
+
+
+SQLiteDatabase::SQLiteDatabase(boost::filesystem::path path)
+{
+#ifdef DCPOMATIC_WINDOWS
+       auto rc = sqlite3_open16(path.c_str(), &_db);
+#else
+       auto rc = sqlite3_open(path.c_str(), &_db);
+#endif
+       if (rc != SQLITE_OK) {
+               throw FileError("Could not open SQLite database", path);
+       }
+
+       sqlite3_busy_timeout(_db, 500);
+}
+
+
+SQLiteDatabase::SQLiteDatabase(SQLiteDatabase&& other)
+{
+       _db = other._db;
+       other._db = nullptr;
+}
+
+
+SQLiteDatabase&
+SQLiteDatabase::operator=(SQLiteDatabase&& other)
+{
+       if (this != &other) {
+               _db = other._db;
+               other._db = nullptr;
+       }
+       return *this;
+}
+
+
+SQLiteDatabase::~SQLiteDatabase()
+{
+       if (_db) {
+               sqlite3_close(_db);
+       }
+}
+
+
diff --git a/src/lib/sqlite_database.h b/src/lib/sqlite_database.h
new file mode 100644 (file)
index 0000000..7858cbf
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+    Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef DCPOMATIC_SQLITE_DATABASE_H
+#define DCPOMATIC_SQLITE_DATABASE_H
+
+
+#include <boost/filesystem.hpp>
+
+struct sqlite3;
+
+
+class SQLiteDatabase
+{
+public:
+       SQLiteDatabase(boost::filesystem::path path);
+       ~SQLiteDatabase();
+
+       SQLiteDatabase(SQLiteDatabase const&) = delete;
+       SQLiteDatabase& operator=(SQLiteDatabase const&) = delete;
+
+       SQLiteDatabase(SQLiteDatabase&&);
+       SQLiteDatabase& operator=(SQLiteDatabase&& other);
+
+       sqlite3* db() const {
+               return _db;
+       }
+
+private:
+       sqlite3* _db = nullptr;
+};
+
+
+#endif
index b3ec1fb813750ae733191b27144ee61810c77204..d130da507a4ac4372c95e5c697cda1fa52131ece 100644 (file)
@@ -20,6 +20,7 @@
 
 
 #include "exceptions.h"
+#include "sqlite_database.h"
 #include "sqlite_statement.h"
 
 
@@ -27,13 +28,13 @@ using std::function;
 using std::string;
 
 
-SQLiteStatement::SQLiteStatement(sqlite3* db, string const& statement)
+SQLiteStatement::SQLiteStatement(SQLiteDatabase& db, string const& statement)
        : _db(db)
 {
 #ifdef DCPOMATIC_HAVE_SQLITE3_PREPARE_V3
-       auto rc = sqlite3_prepare_v3(_db, statement.c_str(), -1, 0, &_stmt, nullptr);
+       auto rc = sqlite3_prepare_v3(_db.db(), statement.c_str(), -1, 0, &_stmt, nullptr);
 #else
-       auto rc = sqlite3_prepare_v2(_db, statement.c_str(), -1, &_stmt, nullptr);
+       auto rc = sqlite3_prepare_v2(_db.db(), statement.c_str(), -1, &_stmt, nullptr);
 #endif
        if (rc != SQLITE_OK) {
                throw SQLError(_db, rc, statement);
@@ -83,7 +84,7 @@ SQLiteStatement::execute(function<void(SQLiteStatement&)> row, function<void()>
                        break;
                case SQLITE_ERROR:
                case SQLITE_MISUSE:
-                       throw SQLError(_db, sqlite3_errmsg(_db));
+                       throw SQLError(_db, sqlite3_errmsg(_db.db()));
                }
        }
 }
index 3c2246efb78fc5f45e1d48ab14710322f48aa0fb..f1131e899b9661d07b733afdc37e2657b87982c9 100644 (file)
 #include <string>
 
 
+class SQLiteDatabase;
+
+
 class SQLiteStatement
 {
 public:
-       SQLiteStatement(sqlite3* db, std::string const& statement);
+       SQLiteStatement(SQLiteDatabase& db, std::string const& statement);
        ~SQLiteStatement();
 
        SQLiteStatement(SQLiteStatement const&) = delete;
@@ -44,7 +47,7 @@ public:
        int data_count();
 
 private:
-       sqlite3* _db;
+       SQLiteDatabase& _db;
        sqlite3_stmt* _stmt;
 };
 
index 239d8502034541803d1cdbd0ce57d1096853bf48..b03dc6499f4d9912924cb6ca50b948bdf8ac1ec7 100644 (file)
@@ -23,7 +23,7 @@
 #include "sqlite_transaction.h"
 
 
-SQLiteTransaction::SQLiteTransaction(sqlite3* db)
+SQLiteTransaction::SQLiteTransaction(SQLiteDatabase& db)
        : _db(db)
 {
        SQLiteStatement statement(_db, "BEGIN TRANSACTION");
index 0f631924320fe921b15ab18574ff5a6f3c0ba58a..b1ec4d6ebc692aca67d25b2c28a69c5ed9021d4d 100644 (file)
 */
 
 
-#include <sqlite3.h>
+class SQLiteDatabase;
 
 
 class SQLiteTransaction
 {
 public:
-       SQLiteTransaction(sqlite3* db);
+       SQLiteTransaction(SQLiteDatabase& db);
        ~SQLiteTransaction();
 
        SQLiteTransaction(SQLiteTransaction const&) = delete;
@@ -34,7 +34,7 @@ public:
        void commit();
 
 private:
-       sqlite3* _db;
+       SQLiteDatabase& _db;
        bool _rollback = true;
 };
 
index 8a4b17dbc98039d0d3b6bcfffaee308fc08f8647..2855041b2364cdfa1c059a0e3c6aa8fd7f1c70de 100644 (file)
@@ -192,6 +192,7 @@ sources = """
           state.cc
           spl.cc
           spl_entry.cc
+          sqlite_database.cc
           sqlite_statement.cc
           sqlite_table.cc
           sqlite_transaction.cc