Add sticker sub-commands inc and dec
Let sqlite do the work for incrementing or decrementing a sticker value. This sub-commands are usefull to track playcounts with sticker values and saves us one roundtrip.
This commit is contained in:
1
NEWS
1
NEWS
@@ -18,6 +18,7 @@ ver 0.24 (not yet released)
|
||||
- volume command is no longer deprecated
|
||||
- new "available" and "reset" subcommands for tagtypes
|
||||
- searching stored playlists respond now with song position
|
||||
- new sticker subcommand "inc" and "dec"
|
||||
* database
|
||||
- attribute "added" shows when each song was added to the database
|
||||
- fix integer overflows with 64-bit inode numbers
|
||||
|
@@ -1518,6 +1518,20 @@ the database for songs).
|
||||
sticker item with that name already exists, it is
|
||||
replaced.
|
||||
|
||||
.. _command_sticker_inc:
|
||||
|
||||
:command:`sticker inc {TYPE} {URI} {NAME} {VALUE}`
|
||||
Adds a sticker value to the specified object. If a
|
||||
sticker item with that name already exists, it is
|
||||
incremented by supplied value.
|
||||
|
||||
.. _command_sticker_dec:
|
||||
|
||||
:command:`sticker dec {TYPE} {URI} {NAME} {VALUE}`
|
||||
Adds a sticker value to the specified object. If a
|
||||
sticker item with that name already exists, it is
|
||||
decremented by supplied value.
|
||||
|
||||
.. _command_sticker_delete:
|
||||
|
||||
:command:`sticker delete {TYPE} {URI} [NAME]`
|
||||
|
@@ -58,6 +58,24 @@ public:
|
||||
return CommandResult::OK;
|
||||
}
|
||||
|
||||
virtual CommandResult Inc(const char *uri, const char *name, const char *value) {
|
||||
sticker_database.IncValue(sticker_type,
|
||||
ValidateUri(uri).c_str(),
|
||||
name,
|
||||
value);
|
||||
|
||||
return CommandResult::OK;
|
||||
}
|
||||
|
||||
virtual CommandResult Dec(const char *uri, const char *name, const char *value) {
|
||||
sticker_database.DecValue(sticker_type,
|
||||
ValidateUri(uri).c_str(),
|
||||
name,
|
||||
value);
|
||||
|
||||
return CommandResult::OK;
|
||||
}
|
||||
|
||||
virtual CommandResult Delete(const char *uri, const char *name) {
|
||||
std::string validated_uri = ValidateUri(uri);
|
||||
uri = validated_uri.c_str();
|
||||
@@ -442,6 +460,14 @@ handle_sticker(Client &client, Request args, Response &r)
|
||||
/* set */
|
||||
if (args.size() == 5 && StringIsEqual(cmd, "set"))
|
||||
return handler->Set(uri, sticker_name, args[4]);
|
||||
|
||||
/* inc */
|
||||
if (args.size() == 5 && StringIsEqual(cmd, "inc"))
|
||||
return handler->Inc(uri, sticker_name, args[4]);
|
||||
|
||||
/* dec */
|
||||
if (args.size() == 5 && StringIsEqual(cmd, "dec"))
|
||||
return handler->Dec(uri, sticker_name, args[4]);
|
||||
|
||||
/* delete */
|
||||
if ((args.size() == 3 || args.size() == 4) && StringIsEqual(cmd, "delete"))
|
||||
|
@@ -48,6 +48,8 @@ enum sticker_sql {
|
||||
STICKER_SQL_NAMES,
|
||||
STICKER_SQL_NAMES_TYPES,
|
||||
STICKER_SQL_NAMES_TYPES_BY_TYPE,
|
||||
STICKER_SQL_INC,
|
||||
STICKER_SQL_DEC,
|
||||
|
||||
STICKER_SQL_COUNT
|
||||
};
|
||||
@@ -115,6 +117,16 @@ static constexpr auto sticker_sql = std::array {
|
||||
|
||||
//[STICKER_SQL_NAMES_TYPES_BY_TYPE]
|
||||
"SELECT name,type FROM sticker WHERE type = ? GROUP BY name,type ORDER BY name",
|
||||
|
||||
//[STICKER_SQL_INC] =
|
||||
"INSERT INTO sticker (type, uri, name, value) VALUES (?, ?, ?, ?) "
|
||||
"ON CONFLICT(type, uri, name) DO "
|
||||
"UPDATE set value = value + ?",
|
||||
|
||||
//[STICKER_SQL_DEC] =
|
||||
"INSERT INTO sticker (type, uri, name, value) VALUES (?, ?, ?, ?) "
|
||||
"ON CONFLICT(type, uri, name) DO "
|
||||
"UPDATE set value = value - ?",
|
||||
};
|
||||
|
||||
static constexpr const char sticker_sql_create[] =
|
||||
@@ -280,6 +292,52 @@ StickerDatabase::StoreValue(const char *type, const char *uri,
|
||||
InsertValue(type, uri, name, value);
|
||||
}
|
||||
|
||||
void
|
||||
StickerDatabase::IncValue(const char *type, const char *uri,
|
||||
const char *name, const char *value)
|
||||
{
|
||||
sqlite3_stmt *const s = stmt[STICKER_SQL_INC];
|
||||
|
||||
assert(type != nullptr);
|
||||
assert(uri != nullptr);
|
||||
assert(name != nullptr);
|
||||
assert(*name != 0);
|
||||
assert(value != nullptr);
|
||||
|
||||
BindAll(s, type, uri, name, value, value);
|
||||
|
||||
AtScopeExit(s) {
|
||||
sqlite3_reset(s);
|
||||
sqlite3_clear_bindings(s);
|
||||
};
|
||||
|
||||
ExecuteCommand(s);
|
||||
idle_add(IDLE_STICKER);
|
||||
}
|
||||
|
||||
void
|
||||
StickerDatabase::DecValue(const char *type, const char *uri,
|
||||
const char *name, const char *value)
|
||||
{
|
||||
sqlite3_stmt *const s = stmt[STICKER_SQL_DEC];
|
||||
|
||||
assert(type != nullptr);
|
||||
assert(uri != nullptr);
|
||||
assert(name != nullptr);
|
||||
assert(*name != 0);
|
||||
assert(value != nullptr);
|
||||
|
||||
BindAll(s, type, uri, name, value, value);
|
||||
|
||||
AtScopeExit(s) {
|
||||
sqlite3_reset(s);
|
||||
sqlite3_clear_bindings(s);
|
||||
};
|
||||
|
||||
ExecuteCommand(s);
|
||||
idle_add(IDLE_STICKER);
|
||||
}
|
||||
|
||||
bool
|
||||
StickerDatabase::Delete(const char *type, const char *uri)
|
||||
{
|
||||
|
@@ -54,6 +54,8 @@ class StickerDatabase {
|
||||
SQL_NAMES,
|
||||
SQL_NAMES_TYPES,
|
||||
SQL_NAMES_TYPES_BY_TYPE,
|
||||
STICKER_SQL_INC,
|
||||
STICKER_SQL_DEC,
|
||||
|
||||
SQL_COUNT
|
||||
};
|
||||
@@ -118,6 +120,24 @@ public:
|
||||
*/
|
||||
void StoreValue(const char *type, const char *uri,
|
||||
const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* Increments a sticker by value in the specified object. Inserts
|
||||
* the value if object does not exist.
|
||||
*
|
||||
* Throws #SqliteError on error.
|
||||
*/
|
||||
void IncValue(const char *type, const char *uri,
|
||||
const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* Decrements a sticker by value in the specified object. Inserts
|
||||
* the value if object does not exist.
|
||||
*
|
||||
* Throws #SqliteError on error.
|
||||
*/
|
||||
void DecValue(const char *type, const char *uri,
|
||||
const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* Deletes a sticker from the database. All sticker values of the
|
||||
|
@@ -30,6 +30,24 @@ sticker_song_set_value(StickerDatabase &db,
|
||||
db.StoreValue("song", uri.c_str(), name, value);
|
||||
}
|
||||
|
||||
void
|
||||
sticker_song_inc_value(StickerDatabase &db,
|
||||
const LightSong &song,
|
||||
const char *name, const char *value)
|
||||
{
|
||||
const auto uri = song.GetURI();
|
||||
db.IncValue("song", uri.c_str(), name, value);
|
||||
}
|
||||
|
||||
void
|
||||
sticker_song_dec_value(StickerDatabase &db,
|
||||
const LightSong &song,
|
||||
const char *name, const char *value)
|
||||
{
|
||||
const auto uri = song.GetURI();
|
||||
db.DecValue("song", uri.c_str(), name, value);
|
||||
}
|
||||
|
||||
bool
|
||||
sticker_song_delete(StickerDatabase &db, const char *uri)
|
||||
{
|
||||
|
@@ -34,6 +34,28 @@ sticker_song_set_value(StickerDatabase &db,
|
||||
const LightSong &song,
|
||||
const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* Increments a sticker by value in the specified object. Inserts
|
||||
* the value if object does not exist.
|
||||
*
|
||||
* Throws #SqliteError on error.
|
||||
*/
|
||||
void
|
||||
sticker_song_inc_value(StickerDatabase &db,
|
||||
const LightSong &song,
|
||||
const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* Decrements a sticker by value in the specified object. Inserts
|
||||
* the value if object does not exist.
|
||||
*
|
||||
* Throws #SqliteError on error.
|
||||
*/
|
||||
void
|
||||
sticker_song_dec_value(StickerDatabase &db,
|
||||
const LightSong &song,
|
||||
const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* Deletes a sticker from the database. All values are deleted.
|
||||
*
|
||||
|
Reference in New Issue
Block a user