aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-12-12 20:32:58 +0100
committerMax Kellermann <max@duempel.org>2014-12-12 21:43:54 +0100
commitcfdbaf331e46f304fc705784967b5aadc4325103 (patch)
tree5930b040a6c48c6b443a4425314e80c89e9de33b
parent052d350b194e0963271c057a26cc79952b9cf66b (diff)
downloadmpd-cfdbaf331e46f304fc705784967b5aadc4325103.tar.gz
mpd-cfdbaf331e46f304fc705784967b5aadc4325103.tar.xz
mpd-cfdbaf331e46f304fc705784967b5aadc4325103.zip
sticker/Database: add wrapper for sqlite3_step()
-rw-r--r--src/lib/sqlite/Util.hxx80
-rw-r--r--src/sticker/StickerDatabase.cxx104
2 files changed, 95 insertions, 89 deletions
diff --git a/src/lib/sqlite/Util.hxx b/src/lib/sqlite/Util.hxx
index 539a6653c..3a7d34a13 100644
--- a/src/lib/sqlite/Util.hxx
+++ b/src/lib/sqlite/Util.hxx
@@ -77,4 +77,84 @@ BindAll(sqlite3_stmt *stmt, Args&&... args)
return BindAll2(stmt, 1, std::forward<Args>(args)...);
}
+/**
+ * Call sqlite3_stmt() repepatedly until something other than
+ * SQLITE_BUSY is returned.
+ */
+static int
+ExecuteBusy(sqlite3_stmt *stmt)
+{
+ int result;
+ do {
+ result = sqlite3_step(stmt);
+ } while (result == SQLITE_BUSY);
+
+ return result;
+}
+
+/**
+ * Wrapper for ExecuteBusy() that returns true on SQLITE_ROW.
+ */
+static bool
+ExecuteRow(sqlite3_stmt *stmt)
+{
+ int result = ExecuteBusy(stmt);
+ if (result == SQLITE_ROW)
+ return true;
+
+ if (result != SQLITE_DONE)
+ LogError(sqlite_domain, "sqlite3_step() failed");
+
+ return false;
+}
+
+/**
+ * Wrapper for ExecuteBusy() that interprets everything other than
+ * SQLITE_DONE as error.
+ */
+static bool
+ExecuteCommand(sqlite3_stmt *stmt)
+{
+ int result = ExecuteBusy(stmt);
+ if (result != SQLITE_DONE) {
+ LogError(stmt, "sqlite3_step() failed");
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Wrapper for ExecuteCommand() that returns the number of rows
+ * modified via sqlite3_changes(). Returns -1 on error.
+ */
+static inline int
+ExecuteChanges(sqlite3_stmt *stmt)
+{
+ if (!ExecuteCommand(stmt))
+ return -1;
+
+ return sqlite3_changes(sqlite3_db_handle(stmt));
+}
+
+template<typename F>
+static inline bool
+ExecuteForEach(sqlite3_stmt *stmt, F &&f)
+{
+ while (true) {
+ switch (ExecuteBusy(stmt)) {
+ case SQLITE_ROW:
+ f();
+ break;
+
+ case SQLITE_DONE:
+ return true;
+
+ default:
+ LogError(sqlite_domain, "sqlite3_step() failed");
+ return false;
+ }
+ }
+}
+
#endif
diff --git a/src/sticker/StickerDatabase.cxx b/src/sticker/StickerDatabase.cxx
index 54397cc9a..049750608 100644
--- a/src/sticker/StickerDatabase.cxx
+++ b/src/sticker/StickerDatabase.cxx
@@ -172,21 +172,9 @@ sticker_load_value(const char *type, const char *uri, const char *name)
if (!BindAll(stmt, type, uri, name))
return std::string();
- int ret;
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
std::string value;
- if (ret == SQLITE_ROW) {
- /* record found */
+ if (ExecuteRow(stmt))
value = (const char*)sqlite3_column_text(stmt, 0);
- } else if (ret == SQLITE_DONE) {
- /* no record found */
- } else {
- /* error */
- LogError(sticker_db, "sqlite3_step() failed");
- }
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
@@ -207,33 +195,16 @@ sticker_list_values(std::map<std::string, std::string> &table,
if (!BindAll(stmt, type, uri))
return false;
- int ret;
- do {
- ret = sqlite3_step(stmt);
- switch (ret) {
- const char *name, *value;
-
- case SQLITE_ROW:
- name = (const char*)sqlite3_column_text(stmt, 0);
- value = (const char*)sqlite3_column_text(stmt, 1);
-
+ const bool success = 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));
- break;
- case SQLITE_DONE:
- break;
- case SQLITE_BUSY:
- /* no op */
- break;
- default:
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
- } while (ret != SQLITE_DONE);
+ });
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
- return true;
+ return success;
}
static bool
@@ -253,17 +224,9 @@ sticker_update_value(const char *type, const char *uri,
if (!BindAll(stmt, value, type, uri, name))
return false;
- int ret;
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
+ int ret = ExecuteChanges(stmt);
+ if (ret < 0)
return false;
- }
-
- ret = sqlite3_changes(sticker_db);
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
@@ -289,20 +252,12 @@ sticker_insert_value(const char *type, const char *uri,
if (!BindAll(stmt, type, uri, name, value))
return false;
- int ret;
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
+ if (!ExecuteCommand(stmt))
return false;
- }
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
-
idle_add(IDLE_STICKER);
return true;
}
@@ -336,15 +291,8 @@ sticker_delete(const char *type, const char *uri)
if (!BindAll(stmt, type, uri))
return false;
- int ret;
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
+ if (!ExecuteCommand(stmt))
return false;
- }
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
@@ -365,17 +313,9 @@ sticker_delete_value(const char *type, const char *uri, const char *name)
if (!BindAll(stmt, type, uri, name))
return false;
- int ret;
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
+ int ret = ExecuteChanges(stmt);
+ if (ret < 0)
return false;
- }
-
- ret = sqlite3_changes(sticker_db);
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
@@ -444,28 +384,14 @@ sticker_find(const char *type, const char *base_uri, const char *name,
if (!BindAll(stmt, type, base_uri, name))
return false;
- int ret;
- do {
- ret = sqlite3_step(stmt);
- switch (ret) {
- case SQLITE_ROW:
+ const bool success = ExecuteForEach(stmt, [stmt, func, user_data](){
func((const char*)sqlite3_column_text(stmt, 0),
(const char*)sqlite3_column_text(stmt, 1),
user_data);
- break;
- case SQLITE_DONE:
- break;
- case SQLITE_BUSY:
- /* no op */
- break;
- default:
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
- } while (ret != SQLITE_DONE);
+ });
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
- return true;
+ return success;
}