less preparation

This commit is contained in:
dignifiedquire
2019-07-06 18:12:27 +02:00
parent 8790a2dc52
commit 180bc926b6
5 changed files with 270 additions and 285 deletions

View File

@@ -700,61 +700,53 @@ pub fn dc_search_msgs(
chat_id: uint32_t, chat_id: uint32_t,
query: *const libc::c_char, query: *const libc::c_char,
) -> *mut dc_array_t { ) -> *mut dc_array_t {
let mut success = false; if query.is_null() {
let ret = unsafe { dc_array_new(100 as size_t) }; return std::ptr::null_mut();
}
if !(ret.is_null() || query.is_null()) {
let real_query = to_string(query).trim().to_string(); let real_query = to_string(query).trim().to_string();
if real_query.is_empty() { if real_query.is_empty() {
success = true; return std::ptr::null_mut();
} else { }
let strLikeInText = format!("%{}%", &real_query); let strLikeInText = format!("%{}%", &real_query);
let strLikeBeg = format!("{}%", &real_query); let strLikeBeg = format!("{}%", &real_query);
let rows = if 0 != chat_id { let query = if 0 != chat_id {
dc_sqlite3_prepare(
context,
&context.sql,
"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \ "SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \
AND m.hidden=0 \ AND m.hidden=0 \
AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;" AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;"
).and_then(|mut stmt| stmt.query_map(
params![chat_id as libc::c_int, &strLikeInText, &strLikeBeg],
|row| row.get::<_, i32>(0)
).and_then(|res| res.collect::<rusqlite::Result<Vec<i32>>>()).ok())
} else { } else {
let show_deaddrop = 0;
dc_sqlite3_prepare(
context,
&context.sql,
"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id \ "SELECT m.id, m.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 \ 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 (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;" AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;"
).and_then(|mut stmt|
stmt.query_map(params![
if 0 != show_deaddrop { 2 } else { 0 },
strLikeInText, strLikeBeg,
], |row| row.get::<_, i32>(0)).and_then(|res| res.collect::<rusqlite::Result<Vec<i32>>>()).ok()
)
}; };
if let Some(ids) = rows {
for id in ids { let ret = unsafe { dc_array_new(100 as size_t) };
unsafe { dc_array_add_id(ret, id as u32) };
} let success = context
success = true; .sql
} .query_map(
} query,
params![chat_id as libc::c_int, &strLikeInText, &strLikeBeg],
|row| row.get::<_, i32>(0),
|rows| {
for id in rows {
unsafe { dc_array_add_id(ret, id? as u32) };
} }
Ok(())
},
)
.is_ok();
if success { if success {
ret return ret;
} else { }
if !ret.is_null() { if !ret.is_null() {
unsafe { dc_array_unref(ret) }; unsafe { dc_array_unref(ret) };
} }
0 as *mut dc_array_t std::ptr::null_mut()
}
} }
pub fn dc_is_inbox(_context: &Context, folder_name: impl AsRef<str>) -> bool { pub fn dc_is_inbox(_context: &Context, folder_name: impl AsRef<str>) -> bool {

View File

@@ -149,9 +149,7 @@ unsafe fn dc_chatlist_load_from_db(
}; };
let success = if query_contact_id != 0 { let success = if query_contact_id != 0 {
if let Some(mut stmt) = dc_sqlite3_prepare( (*chatlist).context.sql.query_map(
(*chatlist).context,
&(*chatlist).context.sql,
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \ "SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
ON c.id=m.chat_id \ ON c.id=m.chat_id \
AND m.timestamp=( SELECT MAX(timestamp) \ AND m.timestamp=( SELECT MAX(timestamp) \
@@ -159,17 +157,12 @@ unsafe fn dc_chatlist_load_from_db(
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \ AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
AND c.blocked=0 AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?) \ AND c.blocked=0 AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?) \
GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;", GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
) { params![query_contact_id as i32],
stmt.query_map(params![query_contact_id as i32], process_fn) process_fn,
.and_then(|res| res.collect::<rusqlite::Result<Vec<_>>>()) |res| res.collect::<rusqlite::Result<Vec<_>>>(),
.is_ok() )
} else {
false
}
} else if 0 != listflags & 0x1 { } else if 0 != listflags & 0x1 {
if let Some(mut stmt) = dc_sqlite3_prepare( (*chatlist).context.sql.query_map(
(*chatlist).context,
&(*chatlist).context.sql,
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \ "SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
ON c.id=m.chat_id \ ON c.id=m.chat_id \
AND m.timestamp=( SELECT MAX(timestamp) \ AND m.timestamp=( SELECT MAX(timestamp) \
@@ -177,13 +170,10 @@ unsafe fn dc_chatlist_load_from_db(
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \ AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
AND c.blocked=0 AND c.archived=1 GROUP BY c.id \ AND c.blocked=0 AND c.archived=1 GROUP BY c.id \
ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;", ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
) { params![],
stmt.query_map(params![], process_fn) process_fn,
.and_then(|res| res.collect::<rusqlite::Result<Vec<_>>>()) |res| res.collect::<rusqlite::Result<Vec<_>>>(),
.is_ok() )
} else {
false
}
} else if query__.is_null() { } else if query__.is_null() {
if 0 == listflags & 0x2 { if 0 == listflags & 0x2 {
let last_deaddrop_fresh_msg_id = get_last_deaddrop_fresh_msg((*chatlist).context); let last_deaddrop_fresh_msg_id = get_last_deaddrop_fresh_msg((*chatlist).context);
@@ -193,9 +183,7 @@ unsafe fn dc_chatlist_load_from_db(
} }
add_archived_link_item = 1; add_archived_link_item = 1;
} }
if let Some(mut stmt) = dc_sqlite3_prepare( (*chatlist).context.sql.query_map(
(*chatlist).context,
&(*chatlist).context.sql,
"SELECT c.id, m.id FROM chats c \ "SELECT c.id, m.id FROM chats c \
LEFT JOIN msgs m \ LEFT JOIN msgs m \
ON c.id=m.chat_id \ ON c.id=m.chat_id \
@@ -205,22 +193,17 @@ unsafe fn dc_chatlist_load_from_db(
AND c.blocked=0 AND c.archived=0 \ AND c.blocked=0 AND c.archived=0 \
GROUP BY c.id \ GROUP BY c.id \
ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;", ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
) { params![],
stmt.query_map(params![], process_fn) process_fn,
.and_then(|res| res.collect::<rusqlite::Result<Vec<_>>>()) |res| res.collect::<rusqlite::Result<Vec<_>>>(),
.is_ok() )
} else {
false
}
} else { } else {
let query = to_string(query__).trim().to_string(); let query = to_string(query__).trim().to_string();
if query.is_empty() { if query.is_empty() {
return 1; return 1;
} else { } else {
let strLikeCmd = format!("%{}%", query); let strLikeCmd = format!("%{}%", query);
if let Some(mut stmt) = dc_sqlite3_prepare( (*chatlist).context.sql.query_map(
(*chatlist).context,
&(*chatlist).context.sql,
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \ "SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
ON c.id=m.chat_id \ ON c.id=m.chat_id \
AND m.timestamp=( SELECT MAX(timestamp) \ AND m.timestamp=( SELECT MAX(timestamp) \
@@ -228,13 +211,10 @@ unsafe fn dc_chatlist_load_from_db(
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \ AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
AND c.blocked=0 AND c.name LIKE ? \ AND c.blocked=0 AND c.name LIKE ? \
GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;", GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
) { params![strLikeCmd],
stmt.query_map(params![strLikeCmd], process_fn) process_fn,
.and_then(|res| res.collect::<rusqlite::Result<Vec<_>>>()) |res| res.collect::<rusqlite::Result<Vec<_>>>(),
.is_ok() )
} else {
false
}
} }
}; };
@@ -248,7 +228,7 @@ unsafe fn dc_chatlist_load_from_db(
} }
(*chatlist).cnt = dc_array_get_cnt((*chatlist).chatNlastmsg_ids).wrapping_div(2); (*chatlist).cnt = dc_array_get_cnt((*chatlist).chatNlastmsg_ids).wrapping_div(2);
success as libc::c_int success.is_ok() as libc::c_int
} }
// Context functions to work with chatlist // Context functions to work with chatlist

View File

@@ -85,38 +85,27 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network:
Ok(job) Ok(job)
}; };
let jobs = if probe_network == 0 { let query = if probe_network == 0 {
if let Some(mut stmt) = dc_sqlite3_prepare(
context,
&context.sql,
"SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries \ "SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries \
FROM jobs WHERE thread=? AND desired_timestamp<=? ORDER BY action DESC, added_timestamp;" FROM jobs WHERE thread=? AND desired_timestamp<=? ORDER BY action DESC, added_timestamp;"
) {
stmt.query_map(params![thread as i64, time()], process_row)
.and_then(|res| res.collect::<rusqlite::Result<Vec<_>>>()).ok()
} else { } else {
None
}
} else {
if let Some(mut stmt) = dc_sqlite3_prepare(
context,
&context.sql,
"SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries \ "SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries \
FROM jobs WHERE thread=? AND tries>0 ORDER BY desired_timestamp, action DESC;", FROM jobs WHERE thread=? AND tries>0 ORDER BY desired_timestamp, action DESC;"
) {
stmt.query_map(params![thread as i64], process_row)
.and_then(|res| res.collect::<rusqlite::Result<Vec<_>>>())
.ok()
} else {
None
}
}; };
if jobs.is_none() { let params_no_probe = params![thread as i64, time()];
return; let params_probe = params![thread as i64];
} let params: &[&dyn rusqlite::ToSql] = if probe_network == 0 {
params_no_probe
} else {
params_probe
};
for mut job in jobs.unwrap() { context
.sql
.query_map(query, params, process_row, |jobs| {
for job in jobs {
let mut job: dc_job_t = job?;
info!( info!(
context, context,
0, 0,
@@ -128,7 +117,11 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network:
if 900 == job.action || 910 == job.action { if 900 == job.action || 910 == job.action {
dc_job_kill_action(context, job.action); dc_job_kill_action(context, job.action);
dc_jobthread_suspend(context, &context.sentbox_thread.clone().read().unwrap(), 1); dc_jobthread_suspend(
context,
&context.sentbox_thread.clone().read().unwrap(),
1,
);
dc_jobthread_suspend(context, &context.mvbox_thread.clone().read().unwrap(), 1); dc_jobthread_suspend(context, &context.mvbox_thread.clone().read().unwrap(), 1);
dc_suspend_smtp_thread(context, 1); dc_suspend_smtp_thread(context, 1);
} }
@@ -243,6 +236,10 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network:
dc_param_unref(job.param); dc_param_unref(job.param);
free(job.pending_error as *mut libc::c_void); free(job.pending_error as *mut libc::c_void);
} }
Ok(())
})
.unwrap(); // TODO: better error handling
} }
fn dc_job_delete(context: &Context, job: &dc_job_t) -> bool { fn dc_job_delete(context: &Context, job: &dc_job_t) -> bool {
@@ -1166,8 +1163,9 @@ pub unsafe fn dc_maybe_network(context: &Context) {
} }
pub fn dc_job_action_exists(context: &Context, action: libc::c_int) -> bool { pub fn dc_job_action_exists(context: &Context, action: libc::c_int) -> bool {
dc_sqlite3_prepare(context, &context.sql, "SELECT id FROM jobs WHERE action=?;") context
.and_then(|mut stmt| stmt.exists(params![action]).ok()) .sql
.exists("SELECT id FROM jobs WHERE action=?;", params![action])
.unwrap_or_default() .unwrap_or_default()
} }

View File

@@ -140,29 +140,27 @@ pub unsafe fn dc_mimefactory_load_msg(
dc_strdup((*factory).from_addr) as *mut libc::c_void, dc_strdup((*factory).from_addr) as *mut libc::c_void,
); );
} else { } else {
let rows = if let Some(mut stmt) = dc_sqlite3_prepare( context
context, .sql
&context.sql, .query_map(
"SELECT c.authname, c.addr \ "SELECT c.authname, c.addr \
FROM chats_contacts cc \ FROM chats_contacts cc \
LEFT JOIN contacts c ON cc.contact_id=c.id \ LEFT JOIN contacts c ON cc.contact_id=c.id \
WHERE cc.chat_id=? AND cc.contact_id>9;", WHERE cc.chat_id=? AND cc.contact_id>9;",
) { params![(*(*factory).msg).chat_id as i32],
stmt.query_map(params![(*(*factory).msg).chat_id as i32], |row| { |row| {
let authname: String = row.get(0)?; let authname: String = row.get(0)?;
let addr: String = row.get(1)?; let addr: String = row.get(1)?;
Ok((authname, addr)) Ok((authname, addr))
}) },
.and_then(|res| res.collect::<rusqlite::Result<Vec<_>>>()) |rows| {
.ok() for row in rows {
} else { let (authname, addr) = row?;
None
};
if let Some(rows) = rows {
for (authname, addr) in rows {
let addr_c = to_cstring(addr); let addr_c = to_cstring(addr);
if clist_search_string_nocase((*factory).recipients_addr, addr_c.as_ptr()) == 0 if clist_search_string_nocase(
(*factory).recipients_addr,
addr_c.as_ptr(),
) == 0
{ {
clist_insert_after( clist_insert_after(
(*factory).recipients_names, (*factory).recipients_names,
@@ -180,7 +178,10 @@ pub unsafe fn dc_mimefactory_load_msg(
); );
} }
} }
} Ok(())
},
)
.unwrap();
let command = dc_param_get_int((*(*factory).msg).param, 'S' as i32, 0); let command = dc_param_get_int((*(*factory).msg).param, 'S' as i32, 0);
if command == 5 { if command == 5 {
@@ -219,21 +220,17 @@ pub unsafe fn dc_mimefactory_load_msg(
} }
} }
let row = dc_sqlite3_prepare( let row = context.sql.query_row(
context,
&context.sql,
"SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?", "SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?",
) params![(*(*factory).msg).id as i32],
.and_then(|mut stmt| { |row| {
stmt.query_row(params![(*(*factory).msg).id as i32], |row| {
let in_reply_to: String = row.get(0)?; let in_reply_to: String = row.get(0)?;
let references: String = row.get(1)?; let references: String = row.get(1)?;
Ok((in_reply_to, references)) Ok((in_reply_to, references))
}) },
.ok() );
}); if let Ok((in_reply_to, references)) = row {
if let Some((in_reply_to, references)) = row {
(*factory).in_reply_to = dc_strdup(to_cstring(in_reply_to).as_ptr()); (*factory).in_reply_to = dc_strdup(to_cstring(in_reply_to).as_ptr());
(*factory).references = dc_strdup(to_cstring(references).as_ptr()); (*factory).references = dc_strdup(to_cstring(references).as_ptr());
} }

View File

@@ -59,6 +59,9 @@ impl SQLite {
self.connection.read().unwrap() self.connection.read().unwrap()
} }
/// Prepares and executes the statement and maps a function over the resulting rows.
/// Then executes the second function over the returned iterator and returns the
/// result of that function.
pub fn query_map<T, P, F, G, H>( pub fn query_map<T, P, F, G, H>(
&self, &self,
sql: &str, sql: &str,
@@ -80,6 +83,21 @@ impl SQLite {
g(res) g(res)
} }
/// Return `true` if a query in the SQL statement it executes returns one or more
/// rows and false if the SQL returns an empty set.
pub fn exists<P>(&self, sql: &str, params: P) -> rusqlite::Result<bool>
where
P: IntoIterator,
P::Item: rusqlite::ToSql,
{
let conn_lock = self.connection.read().unwrap();
let conn = conn_lock.as_ref().expect("database closed");
let mut stmt = conn.prepare(sql)?;
let res = stmt.exists(params)?;
Ok(res)
}
pub fn query_row<T, P, F>(&self, sql: &str, params: P, f: F) -> rusqlite::Result<T> pub fn query_row<T, P, F>(&self, sql: &str, params: P, f: F) -> rusqlite::Result<T>
where where
P: IntoIterator, P: IntoIterator,