Avoid ChatId::is_unset for searching messages

Using a ChatId value of 0 to indicate global search is a left over
from C-land.  Refactor this to be an option instead.
This commit is contained in:
Floris Bruynooghe
2021-02-07 21:54:43 +01:00
parent 6aeda98c0a
commit 65fb2d791b
3 changed files with 52 additions and 39 deletions

View File

@@ -1136,10 +1136,15 @@ pub unsafe extern "C" fn dc_search_msgs(
return ptr::null_mut();
}
let ctx = &*context;
let chat_id = if chat_id == 0 {
None
} else {
Some(ChatId::new(chat_id))
};
block_on(async move {
let arr = dc_array_t::from(
ctx.search_msgs(ChatId::new(chat_id), to_string_lossy(query))
ctx.search_msgs(chat_id, to_string_lossy(query))
.await
.iter()
.map(|msg_id| msg_id.to_u32())

View File

@@ -858,9 +858,9 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
ensure!(!arg1.is_empty(), "Argument <query> missing.");
let chat = if let Some(ref sel_chat) = sel_chat {
sel_chat.get_id()
Some(sel_chat.get_id())
} else {
ChatId::new(0)
None
};
let msglist = context.search_msgs(chat, arg1).await;

View File

@@ -457,48 +457,22 @@ impl Context {
.unwrap_or_default()
}
#[allow(non_snake_case)]
pub async fn search_msgs(&self, chat_id: ChatId, query: impl AsRef<str>) -> Vec<MsgId> {
/// Searches for messages containing the query string.
///
/// If `chat_id` is provided this searches only for messages in this chat, if `chat_id`
/// is `None` this searches messages from all chats.
pub async fn search_msgs(&self, chat_id: Option<ChatId>, query: impl AsRef<str>) -> Vec<MsgId> {
let real_query = query.as_ref().trim();
if real_query.is_empty() {
return Vec::new();
}
let strLikeInText = format!("%{}%", real_query);
let strLikeBeg = format!("{}%", real_query);
let str_like_in_text = format!("%{}%", real_query);
let str_like_beg = format!("{}%", real_query);
let query = if !chat_id.is_unset() {
concat!(
"SELECT m.id AS id, m.timestamp AS timestamp",
" FROM msgs m",
" LEFT JOIN contacts ct",
" ON m.from_id=ct.id",
" WHERE m.chat_id=?",
" AND m.hidden=0",
" AND ct.blocked=0",
" AND (txt LIKE ? OR ct.name LIKE ?)",
" ORDER BY m.timestamp,m.id;"
)
} else {
concat!(
"SELECT m.id AS id, m.timestamp AS timestamp",
" FROM msgs m",
" LEFT JOIN contacts ct",
" ON m.from_id=ct.id",
" LEFT JOIN chats c",
" ON m.chat_id=c.id",
" WHERE m.chat_id>9",
" AND m.hidden=0",
" AND (c.blocked=0 OR c.blocked=?)",
" AND ct.blocked=0",
" AND (m.txt LIKE ? OR ct.name LIKE ?)",
" ORDER BY m.timestamp DESC,m.id DESC;"
)
};
self.sql
.query_map(
let do_query = |query, params| {
self.sql.query_map(
query,
paramsv![chat_id, strLikeInText, strLikeBeg],
params,
|row| row.get::<_, MsgId>("id"),
|rows| {
let mut ret = Vec::new();
@@ -508,8 +482,42 @@ impl Context {
Ok(ret)
},
)
};
if let Some(chat_id) = chat_id {
do_query(
"SELECT m.id AS id, m.timestamp AS timestamp
FROM msgs m
LEFT JOIN contacts ct
ON m.from_id=ct.id
WHERE m.chat_id=?
AND m.hidden=0
AND ct.blocked=0
AND (txt LIKE ? OR ct.name LIKE ?)
ORDER BY m.timestamp,m.id;",
paramsv![chat_id, str_like_in_text, str_like_beg],
)
.await
.unwrap_or_default()
} else {
do_query(
"SELECT m.id AS id, m.timestamp AS timestamp
FROM msgs m
LEFT JOIN contacts ct
ON m.from_id=ct.id
LEFT JOIN chats c
ON m.chat_id=c.id
WHERE m.chat_id>9
AND m.hidden=0
AND c.blocked=0
AND ct.blocked=0
AND (m.txt LIKE ? OR ct.name LIKE ?)
ORDER BY m.timestamp DESC,m.id DESC;",
paramsv![str_like_in_text, str_like_beg],
)
.await
.unwrap_or_default()
}
}
pub async fn is_inbox(&self, folder_name: impl AsRef<str>) -> bool {