From c613d25f29c1bad62da15860f2eb5a38b48bb359 Mon Sep 17 00:00:00 2001 From: jcorporation Date: Sat, 6 Apr 2024 20:08:59 +0200 Subject: [PATCH] Add operators contains and starts_with to sticker find --- doc/protocol.rst | 2 +- src/command/StickerCommands.cxx | 4 ++++ src/sticker/Database.cxx | 23 +++++++++++++++++++++++ src/sticker/Database.hxx | 3 +++ src/sticker/Match.hxx | 12 ++++++++++++ 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/doc/protocol.rst b/doc/protocol.rst index 3a357d342..40fcaa915 100644 --- a/doc/protocol.rst +++ b/doc/protocol.rst @@ -1500,7 +1500,7 @@ the database for songs). Searches for stickers with the given value. Other supported operators are: - "``<``", "``>``" for strings and "``eq``", "``lt``", "``gt``" to cast the value to an integer. + "``<``", "``>``", "``contains``", "``starts_with``" for strings and "``eq``", "``lt``", "``gt``" to cast the value to an integer. Examples: diff --git a/src/command/StickerCommands.cxx b/src/command/StickerCommands.cxx index 99d38f789..f52aefdd5 100644 --- a/src/command/StickerCommands.cxx +++ b/src/command/StickerCommands.cxx @@ -439,6 +439,10 @@ handle_sticker(Client &client, Request args, Response &r) op = StickerOperator::LESS_THAN_INT; else if (StringIsEqual(op_s, "gt")) op = StickerOperator::GREATER_THAN_INT; + else if (StringIsEqual(op_s, "contains")) + op = StickerOperator::CONTAINS; + else if (StringIsEqual(op_s, "starts_with")) + op = StickerOperator::STARTS_WITH; else { r.FmtError(ACK_ERROR_ARG, "bad operator \"{}\"", op_s); return CommandResult::ERROR; diff --git a/src/sticker/Database.cxx b/src/sticker/Database.cxx index 22d8dbb8d..71d4308c7 100644 --- a/src/sticker/Database.cxx +++ b/src/sticker/Database.cxx @@ -28,6 +28,9 @@ enum sticker_sql_find { STICKER_SQL_FIND_LT_INT, STICKER_SQL_FIND_GT_INT, + STICKER_SQL_FIND_CONTAINS, + STICKER_SQL_FIND_STARTS_WITH, + STICKER_SQL_FIND_COUNT }; @@ -68,6 +71,12 @@ static constexpr auto sticker_sql_find = std::array { //[STICKER_SQL_FIND_GT_INT] = "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND CAST(value AS INT)>?", + + //[STICKER_SQL_FIND_CONTAINS] = + "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value LIKE ('%' || ? || '%')", + + //[STICKER_SQL_FIND_STARTS_WITH] = + "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value LIKE (? || '%')", }; static constexpr auto sticker_sql = std::array { @@ -392,6 +401,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::CONTAINS: + sql_str = fmt::format("{} {} {}", + sticker_sql_find[STICKER_SQL_FIND_CONTAINS], order_by, offset); + sql = Prepare(db, sql_str.c_str()); + BindAll(sql, type, base_uri, name, value); + return sql; + + case StickerOperator::STARTS_WITH: + sql_str = fmt::format("{} {} {}", + sticker_sql_find[STICKER_SQL_FIND_STARTS_WITH], order_by, offset); + sql = Prepare(db, sql_str.c_str()); + BindAll(sql, type, base_uri, name, value); + return sql; } assert(false); diff --git a/src/sticker/Database.hxx b/src/sticker/Database.hxx index 726fb9310..91281b3d7 100644 --- a/src/sticker/Database.hxx +++ b/src/sticker/Database.hxx @@ -66,6 +66,9 @@ class StickerDatabase { SQL_FIND_LT_INT, SQL_FIND_GT_INT, + SQL_FIND_CONTAINS, + SQL_FIND_STARTS_WITH, + SQL_FIND_COUNT }; diff --git a/src/sticker/Match.hxx b/src/sticker/Match.hxx index 18c8b1d14..7c05f6cb2 100644 --- a/src/sticker/Match.hxx +++ b/src/sticker/Match.hxx @@ -46,6 +46,18 @@ enum class StickerOperator { * integer value bigger than the specified one. */ GREATER_THAN_INT, + + /** + * Matches if a sticker with the specified name exists and value + * contains given string. + */ + CONTAINS, + + /** + * Matches if a sticker with the specified name exits and value + * starts with given string. + */ + STARTS_WITH, }; #endif