diff options
author | Max Kellermann <max@duempel.org> | 2014-12-12 20:32:58 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2014-12-12 21:43:54 +0100 |
commit | cfdbaf331e46f304fc705784967b5aadc4325103 (patch) | |
tree | 5930b040a6c48c6b443a4425314e80c89e9de33b /src | |
parent | 052d350b194e0963271c057a26cc79952b9cf66b (diff) | |
download | mpd-cfdbaf331e46f304fc705784967b5aadc4325103.tar.gz mpd-cfdbaf331e46f304fc705784967b5aadc4325103.tar.xz mpd-cfdbaf331e46f304fc705784967b5aadc4325103.zip |
sticker/Database: add wrapper for sqlite3_step()
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/sqlite/Util.hxx | 80 | ||||
-rw-r--r-- | src/sticker/StickerDatabase.cxx | 104 |
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; } |