From ceb2b49be5d2a8da38dc40c3ebf3ce7f6b23bd41 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Thu, 20 Jun 2019 23:38:56 +0200 Subject: [PATCH] Some more progress on the rebase fallout and this branch --- src/dc_chat.rs | 6 +- src/dc_e2ee.rs | 2 +- src/dc_imex.rs | 39 +++-------- src/dc_job.rs | 2 +- src/dc_location.rs | 29 +++----- src/dc_mimefactory.rs | 10 +-- src/dc_msg.rs | 153 +++++++++++++++++++----------------------- src/dc_receive_imf.rs | 41 ++--------- src/dc_securejoin.rs | 8 +-- src/dc_sqlite3.rs | 136 +++++++++++++++++++++---------------- src/dc_token.rs | 4 +- 11 files changed, 187 insertions(+), 243 deletions(-) diff --git a/src/dc_chat.rs b/src/dc_chat.rs index 9570a1ff9..d6d7936b3 100644 --- a/src/dc_chat.rs +++ b/src/dc_chat.rs @@ -767,7 +767,7 @@ unsafe fn get_parent_mime_headers( { if let Some(mut stmt) = dc_sqlite3_prepare( (*chat).context, - &mut (*chat).context.sql, + &(*chat).context.sql, "SELECT rfc724_mid, mime_in_reply_to, mime_references \ FROM msgs WHERE timestamp=(SELECT max(timestamp) \ FROM msgs WHERE chat_id=? AND from_id!=?);", @@ -785,7 +785,7 @@ unsafe fn get_parent_mime_headers( if 0 == success { if let Some(mut stmt) = dc_sqlite3_prepare( (*chat).context, - &mut (*chat).context.sql, + &(*chat).context.sql, "SELECT rfc724_mid, mime_in_reply_to, mime_references \ FROM msgs WHERE timestamp=(SELECT min(timestamp) \ FROM msgs WHERE chat_id=? AND from_id==?);", @@ -852,7 +852,7 @@ unsafe fn last_msg_in_chat_encrypted( pub unsafe fn dc_chat_update_param(chat: *mut Chat) -> libc::c_int { dc_sqlite3_execute( (*chat).context, - &mut (*chat).context.sql, + &(*chat).context.sql, "UPDATE chats SET param=? WHERE id=?", params![as_str((*(*chat).param).packed), (*chat).id as i32], ) as libc::c_int diff --git a/src/dc_e2ee.rs b/src/dc_e2ee.rs index 5aa8617c8..cd4c14020 100644 --- a/src/dc_e2ee.rs +++ b/src/dc_e2ee.rs @@ -130,7 +130,7 @@ pub unsafe fn dc_e2ee_encrypt( } let sign_key = if 0 != do_encrypt { keyring.add_ref(&public_key); - let key = Key::from_self_private(context, addr, &context.sql); + let key = Key::from_self_private(context, addr.clone(), &context.sql); if key.is_none() { do_encrypt = 0i32; diff --git a/src/dc_imex.rs b/src/dc_imex.rs index e6f77577f..e03df63ba 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -71,12 +71,8 @@ pub unsafe fn dc_imex_has_backup( if name.starts_with("delta-chat") && name.ends_with(".bak") { let sql = SQLite::new(); if sql.open(context, &path, 0x1) { - let curr_backup_time = dc_sqlite3_get_config_int( - context, - &sql, - b"backup_time\x00" as *const u8 as *const libc::c_char, - 0i32, - ) as u64; + let curr_backup_time = + dc_sqlite3_get_config_int(context, &sql, "backup_time", 0) as u64; if curr_backup_time > newest_backup_time { newest_backup_path = Some(path); newest_backup_time = curr_backup_time; @@ -246,8 +242,7 @@ pub unsafe extern "C" fn dc_render_setup_file( if !(0 == dc_ensure_secret_key_exists(context)) { let self_addr = dc_sqlite3_get_config(context, &context.sql, "configured_addr", None) .unwrap_or_default(); - let curr_private_key = - Key::from_self_private(context, self_addr, &context.sql.clone().read().unwrap()); + let curr_private_key = Key::from_self_private(context, self_addr, &context.sql); let e2ee_enabled = dc_sqlite3_get_config_int(context, &context.sql, "e2ee_enabled", 1); let headers = if 0 != e2ee_enabled { @@ -436,12 +431,7 @@ fn set_self_key( error!(context, 0, "File does not contain a private key.",); } - let self_addr = dc_sqlite3_get_config( - context, - &context.sql.clone().read().unwrap(), - "configured_addr", - None, - ); + let self_addr = dc_sqlite3_get_config(context, &context.sql, "configured_addr", None); if self_addr.is_none() { error!(context, 0, "Missing self addr"); @@ -454,7 +444,7 @@ fn set_self_key( &private_key, self_addr.unwrap(), set_default, - &context.sql.clone().read().unwrap(), + &context.sql, ) { error!(context, 0, "Cannot save keypair."); return 0; @@ -462,18 +452,8 @@ fn set_self_key( match preferencrypt.as_str() { "" => 0, - "nopreference" => dc_sqlite3_set_config_int( - context, - &context.sql.clone().read().unwrap(), - "e2ee_enabled", - 0, - ), - "mutual" => dc_sqlite3_set_config_int( - context, - &context.sql.clone().read().unwrap(), - "e2ee_enabled", - 1, - ), + "nopreference" => dc_sqlite3_set_config_int(context, &context.sql, "e2ee_enabled", 0), + "mutual" => dc_sqlite3_set_config_int(context, &context.sql, "e2ee_enabled", 1), _ => 1, } } @@ -955,7 +935,6 @@ The macro avoids weird values of 0% or 100% while still working. */ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_int { let mut current_block: u64; let mut success: libc::c_int = 0; - let mut closed: bool = false; let mut delete_dest_file: libc::c_int = 0; // get a fine backup file name (the name includes the date so that multiple backup instances are possible) @@ -979,8 +958,8 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ dc_housekeeping(context); dc_sqlite3_try_execute(context, &context.sql, "VACUUM;"); - context.sql.close(); - closed = true; + context.sql.close(context); + let mut closed = true; dc_log_info( context, 0, diff --git a/src/dc_job.rs b/src/dc_job.rs index f9703230a..ab7dad5dc 100644 --- a/src/dc_job.rs +++ b/src/dc_job.rs @@ -512,7 +512,7 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(context: &Context, job: &mut dc_job_t) { * IMAP-jobs ******************************************************************************/ fn connect_to_inbox(context: &Context, inbox: &Imap) -> libc::c_int { - let ret_connected = unsafe { dc_connect_to_configured_imap(context, inbox) }; + let ret_connected = dc_connect_to_configured_imap(context, inbox); if 0 != ret_connected { inbox.set_watch_folder("INBOX".into()); } diff --git a/src/dc_location.rs b/src/dc_location.rs index e5ac052a0..ee2e63d90 100644 --- a/src/dc_location.rs +++ b/src/dc_location.rs @@ -147,7 +147,7 @@ pub fn dc_set_location( let mut continue_streaming = false; let rows = if let Some(mut stmt) = dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT id FROM chats WHERE locations_send_until>?;", ) { stmt.query_map(params![time()], |row| row.get::<_, i32>(0)) @@ -175,7 +175,7 @@ pub fn dc_set_location( continue_streaming = true; } if continue_streaming { - context.call_cb(Event::LOCATION_CHANGED, 1 as uintptr_t, 0 as uintptr_t) + context.call_cb(Event::LOCATION_CHANGED, 1, 0); }; unsafe { schedule_MAYBE_SEND_LOCATIONS(context, 0) }; } @@ -273,8 +273,7 @@ pub fn dc_delete_all_locations(context: &Context) -> bool { if !dc_sqlite3_execute(context, &context.sql, "DELETE FROM locations;", params![]) { return false; } - - unsafe { (context.cb)(context, Event::LOCATION_CHANGED, 0, 0) }; + context.call_cb(Event::LOCATION_CHANGED, 0, 0); true } @@ -298,7 +297,7 @@ pub fn dc_get_location_kml( if let Some((locations_send_begin, locations_send_until, locations_last_sent)) = dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT locations_send_begin, locations_send_until, locations_last_sent FROM chats WHERE id=?;", ).and_then(|mut stmt| { @@ -318,7 +317,7 @@ pub fn dc_get_location_kml( let rows = if let Some(mut stmt) = dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT id, latitude, longitude, accuracy, timestamp\ FROM locations WHERE from_id=? \ AND timestamp>=? \ @@ -444,17 +443,14 @@ pub unsafe fn dc_save_locations( return 0; } - let sql_raw = &context.sql.clone(); - let sql = sql_raw.read().unwrap(); - let stmt_test = dc_sqlite3_prepare( context, - &sql, + &context.sql, "SELECT id FROM locations WHERE timestamp=? AND from_id=?", ); let stmt_insert = dc_sqlite3_prepare( context, - &sql, + &context.sql, "INSERT INTO locations\ (timestamp, from_id, chat_id, latitude, longitude, accuracy, independent) \ VALUES (?,?,?,?,?,?,?);", @@ -714,11 +710,9 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: *mu Ok(Some((chat_id, locations_send_begin, locations_last_sent))) } }) { - let sql_raw = context.sql.clone(); - let sql = sql_raw.read().unwrap(); let stmt_locations = dc_sqlite3_prepare( context, - &sql, + &context.sql, "SELECT id \ FROM locations \ WHERE from_id=? \ @@ -809,11 +803,10 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context: &Context, job: &mut 0, ); dc_add_device_msg(context, chat_id, stock_str); - (context.cb)( - context, + context.call_cb( Event::CHAT_MODIFIED, - chat_id as uintptr_t, - 0 as uintptr_t, + chat_id as usize, + 0, ); } } diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index 78f1369c2..5bb951b99 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -142,7 +142,7 @@ pub unsafe fn dc_mimefactory_load_msg( } else { let rows = if let Some(mut stmt) = dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT c.authname, c.addr \ FROM chats_contacts cc \ LEFT JOIN contacts c ON cc.contact_id=c.id \ @@ -221,7 +221,7 @@ pub unsafe fn dc_mimefactory_load_msg( let row = dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?", ) .and_then(|mut stmt| { @@ -255,7 +255,7 @@ unsafe fn load_from(mut factory: *mut dc_mimefactory_t) { to_cstring( dc_sqlite3_get_config( (*factory).context, - &mut (*factory).context.sql, + &(*factory).context.sql, "configured_addr", None, ) @@ -267,7 +267,7 @@ unsafe fn load_from(mut factory: *mut dc_mimefactory_t) { to_cstring( dc_sqlite3_get_config( (*factory).context, - &mut (*factory).context.sql, + &(*factory).context.sql, "displayname", None, ) @@ -279,7 +279,7 @@ unsafe fn load_from(mut factory: *mut dc_mimefactory_t) { to_cstring( dc_sqlite3_get_config( (*factory).context, - &mut (*factory).context.sql, + &(*factory).context.sql, "selfstatus", None, ) diff --git a/src/dc_msg.rs b/src/dc_msg.rs index 3526675ce..30a36f9d7 100644 --- a/src/dc_msg.rs +++ b/src/dc_msg.rs @@ -534,9 +534,8 @@ pub unsafe fn dc_markseen_msgs(context: &Context, msg_ids: *const u32, msg_cnt: if msg_ids.is_null() || msg_cnt <= 0 { return; } - let sql = context.sql; let stmt = dc_sqlite3_prepare( - context, &sql, + context, &context.sql, "SELECT m.state, c.blocked FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.id=? AND m.chat_id>9" ); @@ -599,8 +598,11 @@ pub fn dc_star_msgs( if msg_ids.is_null() || msg_cnt <= 0 || star != 0 && star != 1 { return false; } - let sql = context.sql; - let stmt = dc_sqlite3_prepare(context, &sql, "UPDATE msgs SET starred=? WHERE id=?;"); + let stmt = dc_sqlite3_prepare( + context, + &context.sql, + "UPDATE msgs SET starred=? WHERE id=?;", + ); if stmt.is_none() { return false; } @@ -1229,7 +1231,7 @@ pub unsafe fn dc_mdn_from_ext( if let Some((msg_id, chat_id, chat_type, msg_state)) = dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT m.id, c.id, c.type, m.state FROM msgs m \ LEFT JOIN chats c ON m.chat_id=c.id \ WHERE rfc724_mid=? AND from_id=1 \ @@ -1313,58 +1315,49 @@ pub unsafe fn dc_mdn_from_ext( /* the number of messages assigned to real chat (!=deaddrop, !=trash) */ pub fn dc_get_real_msg_cnt(context: &Context) -> libc::c_int { - if let Some(conn) = context.sql.conn() { - match conn.query_row( - "SELECT COUNT(*) \ - FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.id>9 AND m.chat_id>9 AND c.blocked=0;", - rusqlite::NO_PARAMS, - |row| row.get(0) - ) { - Ok(res) => res, - Err(err) => { - error!(context, 0, "dc_get_real_msg_cnt() failed. {}", err); - 0 - } + match context.sql.query_row( + "SELECT COUNT(*) \ + FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id \ + WHERE m.id>9 AND m.chat_id>9 AND c.blocked=0;", + rusqlite::NO_PARAMS, + |row| row.get(0), + ) { + Ok(res) => res, + Err(err) => { + error!(context, 0, "dc_get_real_msg_cnt() failed. {}", err); + 0 } - } else { - 0 } } pub fn dc_get_deaddrop_msg_cnt(context: &Context) -> size_t { - if let Some(conn) = context.sql.conn() { - match conn.query_row( - "SELECT COUNT(*) FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE c.blocked=2;", - rusqlite::NO_PARAMS, - |row| row.get::<_, isize>(0), - ) { - Ok(res) => res as size_t, - Err(err) => { - error!(context, 0, "dc_get_deaddrop_msg_cnt() failed. {}", err); - 0 - } + match context.sql.query_row( + "SELECT COUNT(*) \ + FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id \ + WHERE c.blocked=2;", + rusqlite::NO_PARAMS, + |row| row.get::<_, isize>(0), + ) { + Ok(res) => res as size_t, + Err(err) => { + error!(context, 0, "dc_get_deaddrop_msg_cnt() failed. {}", err); + 0 } - } else { - 0 } } pub fn dc_rfc724_mid_cnt(context: &Context, rfc724_mid: *const libc::c_char) -> libc::c_int { /* check the number of messages with the same rfc724_mid */ - if let Some(conn) = context.sql.conn() { - match conn.query_row( - "SELECT COUNT(*) FROM msgs WHERE rfc724_mid=?;", - &[as_str(rfc724_mid)], - |row| row.get(0), - ) { - Ok(res) => res, - Err(err) => { - error!(context, 0, "dc_get_rfc724_mid_cnt() failed. {}", err); - 0 - } + match context.sql.query_row( + "SELECT COUNT(*) FROM msgs WHERE rfc724_mid=?;", + &[as_str(rfc724_mid)], + |row| row.get(0), + ) { + Ok(res) => res, + Err(err) => { + error!(context, 0, "dc_get_rfc724_mid_cnt() failed. {}", err); + 0 } - } else { - 0 } } @@ -1377,38 +1370,32 @@ pub fn dc_rfc724_mid_exists( if rfc724_mid.is_null() || unsafe { *rfc724_mid.offset(0) as libc::c_int } == 0 { return 0; } - - if let Some(conn) = context.sql.conn() { - match conn.query_row( - "SELECT server_folder, server_uid, id FROM msgs WHERE rfc724_mid=?", - &[as_str(rfc724_mid)], - |row| { - if !ret_server_folder.is_null() { - unsafe { - *ret_server_folder = - dc_strdup(to_cstring(row.get::<_, String>(0)?).as_ptr()) - }; - } - if !ret_server_uid.is_null() { - unsafe { *ret_server_uid = row.get(1)? }; - } - row.get(2) - }, - ) { - Ok(res) => res, - Err(_err) => { - if !ret_server_folder.is_null() { - unsafe { *ret_server_folder = 0 as *mut libc::c_char }; - } - if !ret_server_uid.is_null() { - unsafe { *ret_server_uid = 0 }; - } - - 0 + match context.sql.query_row( + "SELECT server_folder, server_uid, id FROM msgs WHERE rfc724_mid=?", + &[as_str(rfc724_mid)], + |row| { + if !ret_server_folder.is_null() { + unsafe { + *ret_server_folder = dc_strdup(to_cstring(row.get::<_, String>(0)?).as_ptr()) + }; } + if !ret_server_uid.is_null() { + unsafe { *ret_server_uid = row.get(1)? }; + } + row.get(2) + }, + ) { + Ok(res) => res, + Err(_err) => { + if !ret_server_folder.is_null() { + unsafe { *ret_server_folder = 0 as *mut libc::c_char }; + } + if !ret_server_uid.is_null() { + unsafe { *ret_server_uid = 0 }; + } + + 0 } - } else { - 0 } } @@ -1418,15 +1405,13 @@ pub fn dc_update_server_uid( server_folder: impl AsRef, server_uid: uint32_t, ) { - if let Some(conn) = context.sql.conn() { - match conn.execute( - "UPDATE msgs SET server_folder=?, server_uid=? WHERE rfc724_mid=?;", - params![server_folder.as_ref(), server_uid, as_str(rfc724_mid)], - ) { - Ok(_) => {} - Err(err) => { - warn!(context, 0, "msg: failed to update server_uid: {}", err); - } + match context.sql.execute( + "UPDATE msgs SET server_folder=?, server_uid=? WHERE rfc724_mid=?;", + params![server_folder.as_ref(), server_uid, as_str(rfc724_mid)], + ) { + Ok(_) => {} + Err(err) => { + warn!(context, 0, "msg: failed to update server_uid: {}", err); } } } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 8db7550ff..3ab000688 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -455,28 +455,6 @@ pub unsafe fn dc_receive_imf( "save_mime_headers", 0, ); - let mut header_bytes = imf_raw_bytes as libc::c_int; - if 0 != save_mime_headers { - let mut p = strstr( - imf_raw_not_terminated, - b"\r\n\r\n\x00" as *const u8 as *const libc::c_char, - ); - if !p.is_null() { - header_bytes = (p.wrapping_offset_from(imf_raw_not_terminated) - + 4) - as libc::c_int - } else { - p = strstr( - imf_raw_not_terminated, - b"\n\n\x00" as *const u8 as *const libc::c_char, - ); - if !p.is_null() { - header_bytes = - (p.wrapping_offset_from(imf_raw_not_terminated) + 2) - as libc::c_int - } - } - } field = dc_mimeparser_lookup_field( &mime_parser, b"In-Reply-To\x00" as *const u8 as *const libc::c_char, @@ -511,10 +489,9 @@ pub unsafe fn dc_receive_imf( } icnt = carray_count(mime_parser.parts) as size_t; - let sql = context.sql; let mut stmt = dc_sqlite3_prepare( context, - &sql, + &context.sql, "INSERT INTO msgs \ (rfc724_mid, server_folder, server_uid, chat_id, from_id, to_id, timestamp, \ timestamp_sent, timestamp_rcvd, type, state, msgrmsg, txt, txt_raw, param, \ @@ -1614,13 +1591,7 @@ fn create_group_record( return 0; } - dc_sqlite3_get_rowid( - context, - &context.sql.clone().read().unwrap(), - "chats", - "grpid", - as_str(grpid), - ) + dc_sqlite3_get_rowid(context, &context.sql, "chats", "grpid", as_str(grpid)) } unsafe fn create_adhoc_grp_id(context: &Context, member_ids: *mut dc_array_t) -> *mut libc::c_char { @@ -1638,7 +1609,7 @@ unsafe fn create_adhoc_grp_id(context: &Context, member_ids: *mut dc_array_t) -> let rows = if let Some(mut stmt) = dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT addr FROM contacts WHERE id IN(?) AND id!=1", ) { stmt.query_map(params![as_str(member_ids_str)], |row| { @@ -1847,7 +1818,7 @@ unsafe fn check_verified_properties( let fp = peerstate.gossip_key_fingerprint.clone(); if let Some(fp) = fp { peerstate.set_verified(0, &fp, 2); - peerstate.save_to_db(&context.sql.clone().read().unwrap(), false); + peerstate.save_to_db(&context.sql, false); is_verified = 1; } } @@ -1962,7 +1933,7 @@ fn is_known_rfc724_mid(context: &Context, rfc724_mid: *const libc::c_char) -> li return 0; } dc_sqlite3_prepare( - context, &context.sql.clone().read().unwrap(), + context, &context.sql, "SELECT m.id FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id WHERE m.rfc724_mid=? AND m.chat_id>9 AND c.blocked=0;" ).and_then(|mut stmt| stmt.exists(params![as_str(rfc724_mid)]).ok()).unwrap_or_default() as libc::c_int } @@ -2041,7 +2012,7 @@ fn is_msgrmsg_rfc724_mid(context: &Context, rfc724_mid: *const libc::c_char) -> } dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT id FROM msgs WHERE rfc724_mid=? AND msgrmsg!=0 AND chat_id>9;", ) .and_then(|mut stmt| stmt.exists(params![as_str(rfc724_mid)]).ok()) diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index 593f59a2c..c417eaf7f 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -76,13 +76,7 @@ pub unsafe fn dc_get_securejoin_qr( } let self_addr = self_addr.unwrap(); - let self_name = dc_sqlite3_get_config( - context, - &context.sql.clone().read().unwrap(), - "displayname", - Some(""), - ) - .unwrap(); + let self_name = dc_sqlite3_get_config(context, &context.sql, "displayname", Some("")).unwrap(); fingerprint = get_self_fingerprint(context); if fingerprint.is_null() { diff --git a/src/dc_sqlite3.rs b/src/dc_sqlite3.rs index fb04f975d..e1b647724 100644 --- a/src/dc_sqlite3.rs +++ b/src/dc_sqlite3.rs @@ -20,27 +20,26 @@ pub struct SQLite { impl SQLite { pub fn new() -> SQLite { SQLite { - cobj: std::sync::RwLock::new(std::ptr::null_mut()), + connection: std::sync::RwLock::new(None), } } - pub fn conn(&self) -> Option<&Connection> { - self.connection.as_ref() + pub fn is_open(&self) -> bool { + self.connection.read().unwrap().is_some() } - pub fn is_open(&self) -> bool { - !self.cobj.read().unwrap().is_null() - } + // pub fn conn(&self) -> Option<&Connection> { + // self.connection.read().unwrap().as_ref() + // } pub unsafe fn raw(&self) -> Option<*mut sqlite3> { - self.connection.as_ref().map(|c| c.handle()) + self.connection.read().unwrap().as_ref().map(|c| c.handle()) } - // TODO: refactor this further to remove open() and close() - // completely, relying entirely on drop(). pub fn close(&self, context: &Context) { - if !self.connection.is_some() { - self.connection.take(); + let mut conn = self.connection.write().unwrap(); + if conn.is_some() { + conn.take(); // drop closes the connection } info!(context, 0, "Database closed."); @@ -49,11 +48,53 @@ impl SQLite { // return true on success, false on failure pub fn open(&self, context: &Context, dbfile: &std::path::Path, flags: libc::c_int) -> bool { let dbfile_c = dbfile.to_c_string().unwrap(); - unsafe { - match dc_sqlite3_open(context, self, dbfile_c.as_ptr(), flags) { - 1 => true, - _ => false, - } + match dc_sqlite3_open(context, self, dbfile_c.as_ptr(), flags) { + 1 => true, + _ => false, + } + } + + pub fn execute

(&self, sql: &str, params: P) -> rusqlite::Result + where + P: IntoIterator, + P::Item: rusqlite::ToSql, + { + match *self.connection.read().unwrap() { + Some(conn) => conn.execute(sql, params), + None => panic!("Querying closed SQLite database"), + } + } + + pub fn prepare(&self, sql: &str) -> rusqlite::Result { + match *self.connection.read().unwrap() { + Some(conn) => conn.prepare(sql), + None => panic!("Querying closed SQLite database"), + } + } + + pub fn query_row(&self, sql: &str, params: P, f: F) -> rusqlite::Result + where + P: IntoIterator, + P::Item: rusqlite::ToSql, + F: FnOnce(&rusqlite::Row) -> rusqlite::Result, + { + match *self.connection.read().unwrap() { + Some(conn) => conn.query_row(sql, params, f), + None => panic!("Querying closed SQLite database"), + } + } + + pub fn table_exists(&self, name: impl AsRef) -> bool { + match *self.connection.read().unwrap() { + Some(conn) => { + conn.pragma(None, "table_info", &format!("{}", name.as_ref()), |row| { + // will only be executed if the info was found + println!("row: {:?}", row.get::<_, String>(0)?); + Ok(()) + }) + .is_ok() + }, + None => panic!("Querying closed SQLite database"), } } } @@ -82,7 +123,7 @@ pub fn dc_sqlite3_open( return 0; } - if sql.conn().is_some() { + if sql.is_open() { error!( context, 0, "Cannot open, database \"{}\" already opened.", dbfile, @@ -98,17 +139,17 @@ pub fn dc_sqlite3_open( open_flags.insert(OpenFlags::SQLITE_OPEN_CREATE); } - match Connection::open_with_flags(dbfile, open_flags) { + let conn = match Connection::open_with_flags(dbfile, open_flags) { Ok(conn) => { - sql.connection = Some(conn); + let mut sql_conn = sql.connection.write().unwrap(); + *sql_conn = Some(conn); + conn } Err(err) => { error!(context, 0, "Cannot open database: \"{}\".", err); return 0; } - } - - let conn = sql.conn().unwrap(); + }; conn.pragma_update(None, "secure_delete", &"on".to_string()) .expect("failed to enable pragma"); @@ -831,23 +872,18 @@ pub fn dc_sqlite3_set_config( 1 } -/* tools, these functions are compatible to the corresponding sqlite3_* functions */ -/* the result mus be freed using sqlite3_finalize() */ +// TODO: Remove the option from the return type pub fn dc_sqlite3_prepare<'a>( context: &Context, sql: &'a SQLite, querystr: &'a str, ) -> Option> { - if let Some(ref conn) = sql.conn() { - match conn.prepare(querystr) { - Ok(s) => Some(s), - Err(err) => { - error!(context, 0, "Query failed: {} ({})", querystr, err); - None - } + match sql.prepare(querystr) { + Ok(s) => Some(s), + Err(err) => { + error!(context, 0, "Query failed: {} ({})", querystr, err); + None } - } else { - None } } @@ -904,6 +940,7 @@ where } } +// TODO Remove the Option<> from the return type. pub fn dc_sqlite3_query_row( context: &Context, sql: &SQLite, @@ -916,17 +953,12 @@ where P::Item: rusqlite::ToSql, T: rusqlite::types::FromSql, { - if let Some(ref conn) = sql.conn() { - match conn.query_row(query, params, |row| row.get::<_, T>(column)) { - Ok(res) => Some(res), - Err(err) => { - error!(context, 0, "sql: Failed query_row: {}", err); - None - } + match sql.query_row(query, params, |row| row.get::<_, T>(column)) { + Ok(res) => Some(res), + Err(err) => { + error!(context, 0, "sql: Failed query_row: {}", err); + None } - } else { - error!(context, 0, "sql: no connection"); - None } } @@ -955,17 +987,9 @@ pub fn dc_sqlite3_table_exists( sql: &SQLite, name: impl AsRef, ) -> libc::c_int { - match sql.conn() { - Some(ref conn) => { - conn.pragma(None, "table_info", &format!("{}", name.as_ref()), |row| { - // will only be executed if the info was found - println!("row: {:?}", row.get::<_, String>(0)?); - Ok(()) - }) - .map(|_| 1) - .unwrap_or_else(|_| 0) - } - None => 0, + match sql.table_exists(name) { + true => 1, + false => 0, } } @@ -1244,9 +1268,7 @@ fn maybe_add_from_param( ) { let param = unsafe { dc_param_new() }; - if let Some(ref mut stmt) = - dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), query) - { + if let Some(ref mut stmt) = dc_sqlite3_prepare(context, &context.sql, query) { match stmt.query_row(NO_PARAMS, |row| { let v = to_cstring(row.get::<_, String>(0)?); unsafe { diff --git a/src/dc_token.rs b/src/dc_token.rs index b72306399..704117946 100644 --- a/src/dc_token.rs +++ b/src/dc_token.rs @@ -22,7 +22,7 @@ pub fn dc_token_save( // foreign_id may be 0 dc_sqlite3_execute( context, - &context.sql.clone().read().unwrap(), + &context.sql, "INSERT INTO tokens (namespc, foreign_id, token, timestamp) VALUES (?, ?, ?, ?);", params![namespc as i32, foreign_id as i32, as_str(token), time()], ) @@ -57,7 +57,7 @@ pub fn dc_token_exists( dc_sqlite3_prepare( context, - &context.sql.clone().read().unwrap(), + &context.sql, "SELECT id FROM tokens WHERE namespc=? AND token=?;", ) .and_then(|mut stmt| stmt.exists(params![namespc as i32, as_str(token)]).ok())