diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 7918f63d6..a40c8ec6f 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -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()) diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 8d3458ab6..5524eea5d 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -858,9 +858,9 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu ensure!(!arg1.is_empty(), "Argument 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; diff --git a/src/context.rs b/src/context.rs index a307e731d..d137785d3 100644 --- a/src/context.rs +++ b/src/context.rs @@ -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) -> Vec { + /// 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, query: impl AsRef) -> Vec { 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) -> bool {