Skip to content

Commit

Permalink
This commit adds the sort and window parameter to "sticker find"
Browse files Browse the repository at this point in the history
The two new compare operators "gt" and "lt" are casting the values to int.

Sort supports:
- uri: sort by uri
- value: sort by value as string
- value_int: casts value to int

This is an attempt to fix MusicPlayerDaemon#1894.
  • Loading branch information
jcorporation committed Nov 7, 2023
1 parent ec9784f commit 56ecde8
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 6 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ver 0.24 (not yet released)
- stickers on playlists and some tag types
- new command "stickernames"
- "sticker find" supports sort and window parameter
- "sticker find" supports integer comparision
* database
- attribute "added" shows when each song was added to the database
- proxy: require MPD 0.21 or later
Expand Down
4 changes: 2 additions & 2 deletions doc/protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1468,15 +1468,15 @@ the database for songs).
For each matching song, it prints the URI and that one
sticker's value.

``sort`` sorts the result by "``uri``" or "``value``". [#since_0_24]_
``sort`` sorts the result by "``uri``","``value`` or "``value_int``" (casts the sticker value to an integer). [#since_0_24]_

.. _command_sticker_find_value:

:command:`sticker find {TYPE} {URI} {NAME} = {VALUE} [sort {SORTTYPE}] [window {START:END}]`
Searches for stickers with the given value.

Other supported operators are:
"``<``", "``>``"
"``<``", "``>``" for strings and "``lt``", "``gt``" to cast the value to an integer.

Examples:

Expand Down
9 changes: 8 additions & 1 deletion src/command/StickerCommands.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,10 @@ handle_sticker(Client &client, Request args, Response &r)
descending = true;
++s;
}
if (StringIsEqual(s, "uri") || StringIsEqual(s, "value")) {
if (StringIsEqual(s, "uri") ||
StringIsEqual(s, "value") ||
StringIsEqual(s, "value_int")
) {
sort = s;
}
else {
Expand All @@ -430,6 +433,10 @@ handle_sticker(Client &client, Request args, Response &r)
op = StickerOperator::LESS_THAN;
else if (StringIsEqual(op_s, ">"))
op = StickerOperator::GREATER_THAN;
else if (StringIsEqual(op_s, "lt"))
op = StickerOperator::LESS_THAN_INT;
else if (StringIsEqual(op_s, "gt"))
op = StickerOperator::GREATER_THAN_INT;
else {
r.FmtError(ACK_ERROR_ARG, "bad operator \"{}\"", op_s);
return CommandResult::ERROR;
Expand Down
31 changes: 28 additions & 3 deletions src/sticker/Database.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ enum sticker_sql_find {
STICKER_SQL_FIND_LT,
STICKER_SQL_FIND_GT,

STICKER_SQL_FIND_LT_INT,
STICKER_SQL_FIND_GT_INT,

STICKER_SQL_FIND_COUNT
};

Expand Down Expand Up @@ -55,6 +58,12 @@ static constexpr auto sticker_sql_find = std::array {

//[STICKER_SQL_FIND_GT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value>?",

//[STICKER_SQL_FIND_LT_INT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND CAST(value AS INT)<?",

//[STICKER_SQL_FIND_GT_INT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND CAST(value AS INT)>?",
};

static constexpr auto sticker_sql = std::array {
Expand Down Expand Up @@ -317,13 +326,15 @@ StickerDatabase::BindFind(const char *type, const char *base_uri,

auto order_by = sort[0] == '\0'
? std::string()
: fmt::format("order by {} {}", sort, descending ? "desc" : "asc");
: StringIsEqual(sort, "value_int")
? fmt::format("ORDER BY CAST(value AS INT) {}", descending ? "desc" : "asc")
: fmt::format("ORDER_BY {} {}", sort, descending ? "desc" : "asc");

auto offset = window.IsAll()
? std::string()
: window.IsOpenEnded()
? fmt::format("limit -1 offset {}", window.start)
: fmt::format("limit {} offset {}", window.Count(), window.start);
? fmt::format("LIMIT -1 OFFSET {}", window.start)
: fmt::format("LIMIT {} OFFSET {}", window.Count(), window.start);

std::string sql_str;
sqlite3_stmt *sql;
Expand Down Expand Up @@ -356,6 +367,20 @@ StickerDatabase::BindFind(const char *type, const char *base_uri,
sql = Prepare(db, sql_str.c_str());
BindAll(sql, type, base_uri, name, value);
return sql;

case StickerOperator::LESS_THAN_INT:
sql_str = fmt::format("{} {} {}",
sticker_sql_find[STICKER_SQL_FIND_LT_INT], order_by, offset);
sql = Prepare(db, sql_str.c_str());
BindAll(sql, type, base_uri, name, value);
return sql;

case StickerOperator::GREATER_THAN_INT:
sql_str = fmt::format("{} {} {}",
sticker_sql_find[STICKER_SQL_FIND_GT_INT], order_by, offset);
sql = Prepare(db, sql_str.c_str());
BindAll(sql, type, base_uri, name, value);
return sql;
}

assert(false);
Expand Down
3 changes: 3 additions & 0 deletions src/sticker/Database.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class StickerDatabase {
SQL_FIND_LT,
SQL_FIND_GT,

SQL_FIND_LT_INT,
SQL_FIND_GT_INT,

SQL_FIND_COUNT
};

Expand Down
12 changes: 12 additions & 0 deletions src/sticker/Match.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ enum class StickerOperator {
* value bigger than the specified one.
*/
GREATER_THAN,

/**
* Matches if a sticker with the specified name exists with a
* integer value smaller than the specified one.
*/
LESS_THAN_INT,

/**
* Matches if a sticker with the specified name exists with a
* integer value bigger than the specified one.
*/
GREATER_THAN_INT,
};

#endif

0 comments on commit 56ecde8

Please sign in to comment.