summaryrefslogtreecommitdiff
path: root/src/sticker
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2019-04-24 15:18:01 +0200
committerMax Kellermann <max@musicpd.org>2019-04-25 12:05:18 +0200
commit77c9081f781c4afd975f58b549ed47bd35375ce2 (patch)
tree8ba8657373601e329e0d1de7510833bcea87e6a1 /src/sticker
parentc88d5616f70819ce6e09255aeacc9153f58a56ec (diff)
sticker/Database: wrap in class StickerDatabase
Diffstat (limited to 'src/sticker')
-rw-r--r--src/sticker/Database.cxx216
-rw-r--r--src/sticker/Database.hxx176
-rw-r--r--src/sticker/SongSticker.cxx34
-rw-r--r--src/sticker/SongSticker.hxx19
4 files changed, 227 insertions, 218 deletions
diff --git a/src/sticker/Database.cxx b/src/sticker/Database.cxx
index 5e5f341c5..302ba3e3f 100644
--- a/src/sticker/Database.cxx
+++ b/src/sticker/Database.cxx
@@ -41,6 +41,7 @@ enum sticker_sql {
STICKER_SQL_FIND_VALUE,
STICKER_SQL_FIND_LT,
STICKER_SQL_FIND_GT,
+ STICKER_SQL_COUNT
};
static const char *const sticker_sql[] = {
@@ -80,11 +81,7 @@ static const char sticker_sql_create[] =
" sticker_value ON sticker(type, uri, name);"
"";
-static sqlite3 *sticker_db;
-static sqlite3_stmt *sticker_stmt[ARRAY_SIZE(sticker_sql)];
-
-void
-sticker_global_init(Path path)
+StickerDatabase::StickerDatabase(Path path)
{
assert(!path.IsNull());
@@ -92,20 +89,20 @@ sticker_global_init(Path path)
/* open/create the sqlite database */
- ret = sqlite3_open(path.c_str(), &sticker_db);
+ ret = sqlite3_open(path.c_str(), &db);
if (ret != SQLITE_OK) {
const std::string utf8 = path.ToUTF8();
- throw SqliteError(sticker_db, ret,
+ throw SqliteError(db, ret,
("Failed to open sqlite database '" +
utf8 + "'").c_str());
}
/* create the table and index */
- ret = sqlite3_exec(sticker_db, sticker_sql_create,
+ ret = sqlite3_exec(db, sticker_sql_create,
nullptr, nullptr, nullptr);
if (ret != SQLITE_OK)
- throw SqliteError(sticker_db, ret,
+ throw SqliteError(db, ret,
"Failed to create sticker table");
/* prepare the statements we're going to use */
@@ -113,38 +110,28 @@ sticker_global_init(Path path)
for (unsigned i = 0; i < ARRAY_SIZE(sticker_sql); ++i) {
assert(sticker_sql[i] != nullptr);
- sticker_stmt[i] = Prepare(sticker_db, sticker_sql[i]);
+ stmt[i] = Prepare(db, sticker_sql[i]);
}
}
-void
-sticker_global_finish() noexcept
+StickerDatabase::~StickerDatabase() noexcept
{
- if (sticker_db == nullptr)
- /* not configured */
- return;
+ assert(db != nullptr);
- for (unsigned i = 0; i < ARRAY_SIZE(sticker_stmt); ++i) {
- assert(sticker_stmt[i] != nullptr);
+ for (unsigned i = 0; i < ARRAY_SIZE(stmt); ++i) {
+ assert(stmt[i] != nullptr);
- sqlite3_finalize(sticker_stmt[i]);
+ sqlite3_finalize(stmt[i]);
}
- sqlite3_close(sticker_db);
-}
-
-bool
-sticker_enabled() noexcept
-{
- return sticker_db != nullptr;
+ sqlite3_close(db);
}
std::string
-sticker_load_value(const char *type, const char *uri, const char *name)
+StickerDatabase::LoadValue(const char *type, const char *uri, const char *name)
{
- sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_GET];
+ sqlite3_stmt *const s = stmt[STICKER_SQL_GET];
- assert(sticker_enabled());
assert(type != nullptr);
assert(uri != nullptr);
assert(name != nullptr);
@@ -152,49 +139,48 @@ sticker_load_value(const char *type, const char *uri, const char *name)
if (StringIsEmpty(name))
return std::string();
- BindAll(stmt, type, uri, name);
+ BindAll(s, type, uri, name);
- AtScopeExit(stmt) {
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
+ AtScopeExit(s) {
+ sqlite3_reset(s);
+ sqlite3_clear_bindings(s);
};
std::string value;
- if (ExecuteRow(stmt))
- value = (const char*)sqlite3_column_text(stmt, 0);
+ if (ExecuteRow(s))
+ value = (const char*)sqlite3_column_text(s, 0);
return value;
}
-static void
-sticker_list_values(std::map<std::string, std::string> &table,
- const char *type, const char *uri)
+void
+StickerDatabase::ListValues(std::map<std::string, std::string> &table,
+ const char *type, const char *uri)
{
- sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_LIST];
+ sqlite3_stmt *const s = stmt[STICKER_SQL_LIST];
assert(type != nullptr);
assert(uri != nullptr);
- assert(sticker_enabled());
- BindAll(stmt, type, uri);
+ BindAll(s, type, uri);
- AtScopeExit(stmt) {
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
+ AtScopeExit(s) {
+ sqlite3_reset(s);
+ sqlite3_clear_bindings(s);
};
- ExecuteForEach(stmt, [stmt, &table](){
- const char *name = (const char *)sqlite3_column_text(stmt, 0);
- const char *value = (const char *)sqlite3_column_text(stmt, 1);
- table.insert(std::make_pair(name, value));
- });
+ ExecuteForEach(s, [s, &table](){
+ const char *name = (const char *)sqlite3_column_text(s, 0);
+ const char *value = (const char *)sqlite3_column_text(s, 1);
+ table.insert(std::make_pair(name, value));
+ });
}
-static bool
-sticker_update_value(const char *type, const char *uri,
- const char *name, const char *value)
+bool
+StickerDatabase::UpdateValue(const char *type, const char *uri,
+ const char *name, const char *value)
{
- sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_UPDATE];
+ sqlite3_stmt *const s = stmt[STICKER_SQL_UPDATE];
assert(type != nullptr);
assert(uri != nullptr);
@@ -202,27 +188,25 @@ sticker_update_value(const char *type, const char *uri,
assert(*name != 0);
assert(value != nullptr);
- assert(sticker_enabled());
+ BindAll(s, value, type, uri, name);
- BindAll(stmt, value, type, uri, name);
-
- AtScopeExit(stmt) {
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
+ AtScopeExit(s) {
+ sqlite3_reset(s);
+ sqlite3_clear_bindings(s);
};
- bool modified = ExecuteModified(stmt);
+ bool modified = ExecuteModified(s);
if (modified)
idle_add(IDLE_STICKER);
return modified;
}
-static void
-sticker_insert_value(const char *type, const char *uri,
- const char *name, const char *value)
+void
+StickerDatabase::InsertValue(const char *type, const char *uri,
+ const char *name, const char *value)
{
- sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_INSERT];
+ sqlite3_stmt *const s = stmt[STICKER_SQL_INSERT];
assert(type != nullptr);
assert(uri != nullptr);
@@ -230,24 +214,21 @@ sticker_insert_value(const char *type, const char *uri,
assert(*name != 0);
assert(value != nullptr);
- assert(sticker_enabled());
-
- BindAll(stmt, type, uri, name, value);
+ BindAll(s, type, uri, name, value);
- AtScopeExit(stmt) {
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
+ AtScopeExit(s) {
+ sqlite3_reset(s);
+ sqlite3_clear_bindings(s);
};
- ExecuteCommand(stmt);
+ ExecuteCommand(s);
idle_add(IDLE_STICKER);
}
void
-sticker_store_value(const char *type, const char *uri,
- const char *name, const char *value)
+StickerDatabase::StoreValue(const char *type, const char *uri,
+ const char *name, const char *value)
{
- assert(sticker_enabled());
assert(type != nullptr);
assert(uri != nullptr);
assert(name != nullptr);
@@ -256,67 +237,67 @@ sticker_store_value(const char *type, const char *uri,
if (StringIsEmpty(name))
return;
- if (!sticker_update_value(type, uri, name, value))
- sticker_insert_value(type, uri, name, value);
+ if (!UpdateValue(type, uri, name, value))
+ InsertValue(type, uri, name, value);
}
bool
-sticker_delete(const char *type, const char *uri)
+StickerDatabase::Delete(const char *type, const char *uri)
{
- sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_DELETE];
+ sqlite3_stmt *const s = stmt[STICKER_SQL_DELETE];
- assert(sticker_enabled());
assert(type != nullptr);
assert(uri != nullptr);
- BindAll(stmt, type, uri);
+ BindAll(s, type, uri);
- AtScopeExit(stmt) {
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
+ AtScopeExit(s) {
+ sqlite3_reset(s);
+ sqlite3_clear_bindings(s);
};
- bool modified = ExecuteModified(stmt);
+ bool modified = ExecuteModified(s);
if (modified)
idle_add(IDLE_STICKER);
return modified;
}
bool
-sticker_delete_value(const char *type, const char *uri, const char *name)
+StickerDatabase::DeleteValue(const char *type, const char *uri,
+ const char *name)
{
- sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_DELETE_VALUE];
+ sqlite3_stmt *const s = stmt[STICKER_SQL_DELETE_VALUE];
- assert(sticker_enabled());
assert(type != nullptr);
assert(uri != nullptr);
- BindAll(stmt, type, uri, name);
+ BindAll(s, type, uri, name);
- AtScopeExit(stmt) {
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
+ AtScopeExit(s) {
+ sqlite3_reset(s);
+ sqlite3_clear_bindings(s);
};
- bool modified = ExecuteModified(stmt);
+ bool modified = ExecuteModified(s);
if (modified)
idle_add(IDLE_STICKER);
return modified;
}
Sticker
-sticker_load(const char *type, const char *uri)
+StickerDatabase::Load(const char *type, const char *uri)
{
Sticker s;
- sticker_list_values(s.table, type, uri);
+ ListValues(s.table, type, uri);
return s;
}
-static sqlite3_stmt *
-BindFind(const char *type, const char *base_uri, const char *name,
- StickerOperator op, const char *value)
+sqlite3_stmt *
+StickerDatabase::BindFind(const char *type, const char *base_uri,
+ const char *name,
+ StickerOperator op, const char *value)
{
assert(type != nullptr);
assert(name != nullptr);
@@ -326,23 +307,23 @@ BindFind(const char *type, const char *base_uri, const char *name,
switch (op) {
case StickerOperator::EXISTS:
- BindAll(sticker_stmt[STICKER_SQL_FIND], type, base_uri, name);
- return sticker_stmt[STICKER_SQL_FIND];
+ BindAll(stmt[STICKER_SQL_FIND], type, base_uri, name);
+ return stmt[STICKER_SQL_FIND];
case StickerOperator::EQUALS:
- BindAll(sticker_stmt[STICKER_SQL_FIND_VALUE],
+ BindAll(stmt[STICKER_SQL_FIND_VALUE],
type, base_uri, name, value);
- return sticker_stmt[STICKER_SQL_FIND_VALUE];
+ return stmt[STICKER_SQL_FIND_VALUE];
case StickerOperator::LESS_THAN:
- BindAll(sticker_stmt[STICKER_SQL_FIND_LT],
+ BindAll(stmt[STICKER_SQL_FIND_LT],
type, base_uri, name, value);
- return sticker_stmt[STICKER_SQL_FIND_LT];
+ return stmt[STICKER_SQL_FIND_LT];
case StickerOperator::GREATER_THAN:
- BindAll(sticker_stmt[STICKER_SQL_FIND_GT],
+ BindAll(stmt[STICKER_SQL_FIND_GT],
type, base_uri, name, value);
- return sticker_stmt[STICKER_SQL_FIND_GT];
+ return stmt[STICKER_SQL_FIND_GT];
}
assert(false);
@@ -350,26 +331,25 @@ BindFind(const char *type, const char *base_uri, const char *name,
}
void
-sticker_find(const char *type, const char *base_uri, const char *name,
- StickerOperator op, const char *value,
- void (*func)(const char *uri, const char *value,
- void *user_data),
- void *user_data)
+StickerDatabase::Find(const char *type, const char *base_uri, const char *name,
+ StickerOperator op, const char *value,
+ void (*func)(const char *uri, const char *value,
+ void *user_data),
+ void *user_data)
{
assert(func != nullptr);
- assert(sticker_enabled());
- sqlite3_stmt *const stmt = BindFind(type, base_uri, name, op, value);
- assert(stmt != nullptr);
+ sqlite3_stmt *const s = BindFind(type, base_uri, name, op, value);
+ assert(s != nullptr);
- AtScopeExit(stmt) {
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
+ AtScopeExit(s) {
+ sqlite3_reset(s);
+ sqlite3_clear_bindings(s);
};
- ExecuteForEach(stmt, [stmt, func, user_data](){
- func((const char*)sqlite3_column_text(stmt, 0),
- (const char*)sqlite3_column_text(stmt, 1),
+ ExecuteForEach(s, [s, func, user_data](){
+ func((const char*)sqlite3_column_text(s, 0),
+ (const char*)sqlite3_column_text(s, 1),
user_data);
});
}
diff --git a/src/sticker/Database.hxx b/src/sticker/Database.hxx
index dbaac8080..efc94b3ca 100644
--- a/src/sticker/Database.hxx
+++ b/src/sticker/Database.hxx
@@ -45,96 +45,116 @@
#include "Match.hxx"
#include "util/Compiler.h"
+#include <sqlite3.h>
+
+#include <map>
#include <string>
class Path;
struct Sticker;
-/**
- * Opens the sticker database.
- *
- * Throws std::runtime_error on error.
- */
-void
-sticker_global_init(Path path);
+class StickerDatabase {
+ enum SQL {
+ SQL_GET,
+ SQL_LIST,
+ SQL_UPDATE,
+ SQL_INSERT,
+ SQL_DELETE,
+ SQL_DELETE_VALUE,
+ SQL_FIND,
+ SQL_FIND_VALUE,
+ SQL_FIND_LT,
+ SQL_FIND_GT,
-/**
- * Close the sticker database.
- */
-void
-sticker_global_finish() noexcept;
+ SQL_COUNT
+ };
-/**
- * Returns true if the sticker database is configured and available.
- */
-gcc_const
-bool
-sticker_enabled() noexcept;
+ sqlite3 *db;
+ sqlite3_stmt *stmt[SQL_COUNT];
-/**
- * Returns one value from an object's sticker record. Returns an
- * empty string if the value doesn't exist.
- *
- * Throws #SqliteError on error.
- */
-std::string
-sticker_load_value(const char *type, const char *uri, const char *name);
+public:
+ /**
+ * Opens the sticker database.
+ *
+ * Throws on error.
+ */
+ StickerDatabase(Path path);
+ ~StickerDatabase() noexcept;
-/**
- * Sets a sticker value in the specified object. Overwrites existing
- * values.
- *
- * Throws #SqliteError on error.
- */
-void
-sticker_store_value(const char *type, const char *uri,
- const char *name, const char *value);
+ /**
+ * Returns one value from an object's sticker record. Returns an
+ * empty string if the value doesn't exist.
+ *
+ * Throws #SqliteError on error.
+ */
+ std::string LoadValue(const char *type, const char *uri,
+ const char *name);
-/**
- * Deletes a sticker from the database. All sticker values of the
- * specified object are deleted.
- *
- * Throws #SqliteError on error.
- */
-bool
-sticker_delete(const char *type, const char *uri);
+ /**
+ * Sets a sticker value in the specified object. Overwrites existing
+ * values.
+ *
+ * Throws #SqliteError on error.
+ */
+ void StoreValue(const char *type, const char *uri,
+ const char *name, const char *value);
-/**
- * Deletes a sticker value. Fails if no sticker with this name
- * exists.
- *
- * Throws #SqliteError on error.
- */
-bool
-sticker_delete_value(const char *type, const char *uri, const char *name);
+ /**
+ * Deletes a sticker from the database. All sticker values of the
+ * specified object are deleted.
+ *
+ * Throws #SqliteError on error.
+ */
+ bool Delete(const char *type, const char *uri);
-/**
- * Loads the sticker for the specified resource.
- *
- * Throws #SqliteError on error.
- *
- * @param type the resource type, e.g. "song"
- * @param uri the URI of the resource, e.g. the song path
- * @return a sticker object
- */
-Sticker
-sticker_load(const char *type, const char *uri);
+ /**
+ * Deletes a sticker value. Fails if no sticker with this name
+ * exists.
+ *
+ * Throws #SqliteError on error.
+ */
+ bool DeleteValue(const char *type, const char *uri, const char *name);
-/**
- * Finds stickers with the specified name below the specified URI.
- *
- * @param type the resource type, e.g. "song"
- * @param base_uri the URI prefix of the resources, or nullptr if all
- * resources should be searched
- * @param name the name of the sticker
- * @param op the comparison operator
- * @param value the operand
- */
-void
-sticker_find(const char *type, const char *base_uri, const char *name,
- StickerOperator op, const char *value,
- void (*func)(const char *uri, const char *value,
- void *user_data),
- void *user_data);
+ /**
+ * Loads the sticker for the specified resource.
+ *
+ * Throws #SqliteError on error.
+ *
+ * @param type the resource type, e.g. "song"
+ * @param uri the URI of the resource, e.g. the song path
+ * @return a sticker object
+ */
+ Sticker Load(const char *type, const char *uri);
+
+ /**
+ * Finds stickers with the specified name below the specified URI.
+ *
+ * @param type the resource type, e.g. "song"
+ * @param base_uri the URI prefix of the resources, or nullptr if all
+ * resources should be searched
+ * @param name the name of the sticker
+ * @param op the comparison operator
+ * @param value the operand
+ */
+ void Find(const char *type, const char *base_uri, const char *name,
+ StickerOperator op, const char *value,
+ void (*func)(const char *uri, const char *value,
+ void *user_data),
+ void *user_data);
+
+private:
+ void ListValues(std::map<std::string, std::string> &table,
+ const char *type, const char *uri);
+
+ bool UpdateValue(const char *type, const char *uri,
+ const char *name, const char *value);
+
+ void InsertValue(const char *type, const char *uri,
+ const char *name, const char *value);
+
+ sqlite3_stmt *BindFind(const char *type, const char *base_uri,
+ const char *name,
+ StickerOperator op, const char *value);
+};
#endif
diff --git a/src/sticker/SongSticker.cxx b/src/sticker/SongSticker.cxx
index 1c43f4d04..5b4683672 100644
--- a/src/sticker/SongSticker.cxx
+++ b/src/sticker/SongSticker.cxx
@@ -29,44 +29,47 @@
#include <stdlib.h>
std::string
-sticker_song_get_value(const LightSong &song, const char *name)
+sticker_song_get_value(StickerDatabase &db,
+ const LightSong &song, const char *name)
{
const auto uri = song.GetURI();
- return sticker_load_value("song", uri.c_str(), name);
+ return db.LoadValue("song", uri.c_str(), name);
}
void
-sticker_song_set_value(const LightSong &song,
+sticker_song_set_value(StickerDatabase &db,
+ const LightSong &song,
const char *name, const char *value)
{
const auto uri = song.GetURI();
- sticker_store_value("song", uri.c_str(), name, value);
+ db.StoreValue("song", uri.c_str(), name, value);
}
bool
-sticker_song_delete(const char *uri)
+sticker_song_delete(StickerDatabase &db, const char *uri)
{
- return sticker_delete("song", uri);
+ return db.Delete("song", uri);
}
bool
-sticker_song_delete(const LightSong &song)
+sticker_song_delete(StickerDatabase &db, const LightSong &song)
{
- return sticker_song_delete(song.GetURI().c_str());
+ return sticker_song_delete(db, song.GetURI().c_str());
}
bool
-sticker_song_delete_value(const LightSong &song, const char *name)
+sticker_song_delete_value(StickerDatabase &db,
+ const LightSong &song, const char *name)
{
const auto uri = song.GetURI();
- return sticker_delete_value("song", uri.c_str(), name);
+ return db.DeleteValue("song", uri.c_str(), name);
}
Sticker
-sticker_song_get(const LightSong &song)
+sticker_song_get(StickerDatabase &db, const LightSong &song)
{
const auto uri = song.GetURI();
- return sticker_load("song", uri.c_str());
+ return db.Load("song", uri.c_str());
}
namespace {
@@ -101,7 +104,8 @@ sticker_song_find_cb(const char *uri, const char *value, void *user_data)
}
void
-sticker_song_find(const Database &db, const char *base_uri, const char *name,
+sticker_song_find(StickerDatabase &sticker_database, const Database &db,
+ const char *base_uri, const char *name,
StickerOperator op, const char *value,
void (*func)(const LightSong &song, const char *value,
void *user_data),
@@ -126,6 +130,6 @@ sticker_song_find(const Database &db, const char *base_uri, const char *name,
data.base_uri_length = strlen(data.base_uri);
- sticker_find("song", data.base_uri, name, op, value,
- sticker_song_find_cb, &data);
+ sticker_database.Find("song", data.base_uri, name, op, value,
+ sticker_song_find_cb, &data);
}
diff --git a/src/sticker/SongSticker.hxx b/src/sticker/SongSticker.hxx
index 28f3eca7c..ed76e9c4c 100644
--- a/src/sticker/SongSticker.hxx
+++ b/src/sticker/SongSticker.hxx
@@ -27,6 +27,7 @@
struct LightSong;
struct Sticker;
class Database;
+class StickerDatabase;
/**
* Returns one value from a song's sticker record.
@@ -34,7 +35,8 @@ class Database;
* Throws #SqliteError on error.
*/
std::string
-sticker_song_get_value(const LightSong &song, const char *name);
+sticker_song_get_value(StickerDatabase &db,
+ const LightSong &song, const char *name);
/**
* Sets a sticker value in the specified song. Overwrites existing
@@ -43,7 +45,8 @@ sticker_song_get_value(const LightSong &song, const char *name);
* Throws #SqliteError on error.
*/
void
-sticker_song_set_value(const LightSong &song,
+sticker_song_set_value(StickerDatabase &db,
+ const LightSong &song,
const char *name, const char *value);
/**
@@ -52,10 +55,10 @@ sticker_song_set_value(const LightSong &song,
* Throws #SqliteError on error.
*/
bool
-sticker_song_delete(const char *uri);
+sticker_song_delete(StickerDatabase &db, const char *uri);
bool
-sticker_song_delete(const LightSong &song);
+sticker_song_delete(StickerDatabase &db, const LightSong &song);
/**
* Deletes a sticker value. Does nothing if the sticker did not
@@ -64,7 +67,8 @@ sticker_song_delete(const LightSong &song);
* Throws #SqliteError on error.
*/
bool
-sticker_song_delete_value(const LightSong &song, const char *name);
+sticker_song_delete_value(StickerDatabase &db,
+ const LightSong &song, const char *name);
/**
* Loads the sticker for the specified song.
@@ -75,7 +79,7 @@ sticker_song_delete_value(const LightSong &song, const char *name);
* @return a sticker object
*/
Sticker
-sticker_song_get(const LightSong &song);
+sticker_song_get(StickerDatabase &db, const LightSong &song);
/**
* Finds stickers with the specified name below the specified
@@ -89,7 +93,8 @@ sticker_song_get(const LightSong &song);
* @param name the name of the sticker
*/
void
-sticker_song_find(const Database &db, const char *base_uri, const char *name,
+sticker_song_find(StickerDatabase &sticker_database, const Database &db,
+ const char *base_uri, const char *name,
StickerOperator op, const char *value,
void (*func)(const LightSong &song, const char *value,
void *user_data),