This commit adds the sort and window parameter to "sticker find"

The three new compare operators "eq", "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

Closes #1894
This commit is contained in:
jcorporation
2024-03-07 20:52:11 +01:00
parent 1efb9d41db
commit 45553c5f61
8 changed files with 187 additions and 42 deletions

View File

@@ -10,6 +10,7 @@
#include "util/StringCompare.hxx"
#include "util/ScopeExit.hxx"
#include <fmt/format.h>
#include <cassert>
#include <iterator>
#include <array>
@@ -17,6 +18,19 @@
using namespace Sqlite;
enum sticker_sql_find {
STICKER_SQL_FIND,
STICKER_SQL_FIND_VALUE,
STICKER_SQL_FIND_LT,
STICKER_SQL_FIND_GT,
STICKER_SQL_FIND_EQ_INT,
STICKER_SQL_FIND_LT_INT,
STICKER_SQL_FIND_GT_INT,
STICKER_SQL_FIND_COUNT
};
enum sticker_sql {
STICKER_SQL_GET,
STICKER_SQL_LIST,
@@ -24,10 +38,6 @@ enum sticker_sql {
STICKER_SQL_INSERT,
STICKER_SQL_DELETE,
STICKER_SQL_DELETE_VALUE,
STICKER_SQL_FIND,
STICKER_SQL_FIND_VALUE,
STICKER_SQL_FIND_LT,
STICKER_SQL_FIND_GT,
STICKER_SQL_DISTINCT_TYPE_URI,
STICKER_SQL_TRANSACTION_BEGIN,
STICKER_SQL_TRANSACTION_COMMIT,
@@ -37,6 +47,29 @@ enum sticker_sql {
STICKER_SQL_COUNT
};
static constexpr auto sticker_sql_find = std::array {
//[STICKER_SQL_FIND] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=?",
//[STICKER_SQL_FIND_VALUE] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value=?",
//[STICKER_SQL_FIND_LT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value<?",
//[STICKER_SQL_FIND_GT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value>?",
//[STICKER_SQL_FIND_EQ_INT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND CAST(value AS INT)=?",
//[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 {
//[STICKER_SQL_GET] =
"SELECT value FROM sticker WHERE type=? AND uri=? AND name=?",
@@ -50,17 +83,6 @@ static constexpr auto sticker_sql = std::array {
"DELETE FROM sticker WHERE type=? AND uri=?",
//[STICKER_SQL_DELETE_VALUE] =
"DELETE FROM sticker WHERE type=? AND uri=? AND name=?",
//[STICKER_SQL_FIND] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=?",
//[STICKER_SQL_FIND_VALUE] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value=?",
//[STICKER_SQL_FIND_LT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value<?",
//[STICKER_SQL_FIND_GT] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value>?",
//[STICKER_SQL_DISTINCT_TYPE_URI] =
"SELECT DISTINCT type,uri FROM sticker",
@@ -297,7 +319,8 @@ StickerDatabase::Load(const char *type, const char *uri)
sqlite3_stmt *
StickerDatabase::BindFind(const char *type, const char *base_uri,
const char *name,
StickerOperator op, const char *value)
StickerOperator op, const char *value,
const char *sort, bool descending, RangeArg window)
{
assert(type != nullptr);
assert(name != nullptr);
@@ -305,25 +328,70 @@ StickerDatabase::BindFind(const char *type, const char *base_uri,
if (base_uri == nullptr)
base_uri = "";
auto order_by = StringIsEmpty(sort)
? std::string()
: 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);
std::string sql_str;
sqlite3_stmt *sql;
switch (op) {
case StickerOperator::EXISTS:
BindAll(stmt[STICKER_SQL_FIND], type, base_uri, name);
return stmt[STICKER_SQL_FIND];
sql_str = fmt::format("{} {} {}",
sticker_sql_find[STICKER_SQL_FIND], order_by, offset);
sql = Prepare(db, sql_str.c_str());
BindAll(sql, type, base_uri, name);
return sql;
case StickerOperator::EQUALS:
BindAll(stmt[STICKER_SQL_FIND_VALUE],
type, base_uri, name, value);
return stmt[STICKER_SQL_FIND_VALUE];
sql_str = fmt::format("{} {} {}",
sticker_sql_find[STICKER_SQL_FIND_VALUE], order_by, offset);
sql = Prepare(db, sql_str.c_str());
BindAll(sql, type, base_uri, name, value);
return sql;
case StickerOperator::LESS_THAN:
BindAll(stmt[STICKER_SQL_FIND_LT],
type, base_uri, name, value);
return stmt[STICKER_SQL_FIND_LT];
sql_str = fmt::format("{} {} {}",
sticker_sql_find[STICKER_SQL_FIND_LT], order_by, offset);
sql = Prepare(db, sql_str.c_str());
BindAll(sql, type, base_uri, name, value);
return sql;
case StickerOperator::GREATER_THAN:
BindAll(stmt[STICKER_SQL_FIND_GT],
type, base_uri, name, value);
return stmt[STICKER_SQL_FIND_GT];
sql_str = fmt::format("{} {} {}",
sticker_sql_find[STICKER_SQL_FIND_GT], order_by, offset);
sql = Prepare(db, sql_str.c_str());
BindAll(sql, type, base_uri, name, value);
return sql;
case StickerOperator::EQUALS_INT:
sql_str = fmt::format("{} {} {}",
sticker_sql_find[STICKER_SQL_FIND_EQ_INT], order_by, offset);
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);
@@ -333,18 +401,18 @@ StickerDatabase::BindFind(const char *type, const char *base_uri,
void
StickerDatabase::Find(const char *type, const char *base_uri, const char *name,
StickerOperator op, const char *value,
const char *sort, bool descending, RangeArg window,
void (*func)(const char *uri, const char *value,
void *user_data),
void *user_data)
{
assert(func != nullptr);
sqlite3_stmt *const s = BindFind(type, base_uri, name, op, value);
sqlite3_stmt *const s = BindFind(type, base_uri, name, op, value, sort, descending, window);
assert(s != nullptr);
AtScopeExit(s) {
sqlite3_reset(s);
sqlite3_clear_bindings(s);
sqlite3_finalize(s);
};
ExecuteForEach(s, [s, func, user_data](){