sticker/Database: add wrapper for sqlite3_step()
This commit is contained in:
parent
052d350b19
commit
cfdbaf331e
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue