mirror of
https://github.com/chatmail/core.git
synced 2026-04-02 05:22:14 +03:00
Move SQL errors into their own module
This commit is contained in:
committed by
Floris Bruynooghe
parent
ea8adf39c2
commit
612600278a
19
src/chat.rs
19
src/chat.rs
@@ -64,13 +64,15 @@ impl Chat {
|
||||
);
|
||||
|
||||
match res {
|
||||
Err(err @ crate::error::Error::Sql(rusqlite::Error::QueryReturnedNoRows)) => Err(err),
|
||||
Err(err @ crate::sql::Error::Sql(rusqlite::Error::QueryReturnedNoRows)) => {
|
||||
Err(err.into())
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
context,
|
||||
"chat: failed to load from db {}: {:?}", chat_id, err
|
||||
);
|
||||
Err(err)
|
||||
Err(err.into())
|
||||
}
|
||||
Ok(mut chat) => {
|
||||
match chat.id {
|
||||
@@ -129,7 +131,8 @@ impl Chat {
|
||||
&context.sql,
|
||||
"UPDATE chats SET param=? WHERE id=?",
|
||||
params![self.param.to_string(), self.id as i32],
|
||||
)
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> u32 {
|
||||
@@ -681,7 +684,7 @@ pub fn lookup_by_contact_id(context: &Context, contact_id: u32) -> Result<(u32,
|
||||
"SELECT c.id, c.blocked FROM chats c INNER JOIN chats_contacts j ON c.id=j.chat_id WHERE c.type=100 AND c.id>9 AND j.contact_id=?;",
|
||||
params![contact_id as i32],
|
||||
|row| Ok((row.get(0)?, row.get::<_, Option<_>>(1)?.unwrap_or_default())),
|
||||
)
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn get_by_contact_id(context: &Context, contact_id: u32) -> Result<u32, Error> {
|
||||
@@ -829,7 +832,8 @@ pub fn unarchive(context: &Context, chat_id: u32) -> Result<(), Error> {
|
||||
&context.sql,
|
||||
"UPDATE chats SET archived=0 WHERE id=?",
|
||||
params![chat_id as i32],
|
||||
)
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send a message defined by a dc_msg_t object to a chat.
|
||||
@@ -976,7 +980,8 @@ fn do_set_draft(context: &Context, chat_id: u32, msg: &mut Message) -> Result<()
|
||||
msg.param.to_string(),
|
||||
1,
|
||||
],
|
||||
)
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// similar to as dc_set_draft() but does not emit an event
|
||||
@@ -1688,7 +1693,7 @@ pub fn is_group_explicitly_left(context: &Context, grpid: impl AsRef<str>) -> Re
|
||||
context.sql.exists(
|
||||
"SELECT id FROM leftgrps WHERE grpid=?;",
|
||||
params![grpid.as_ref()],
|
||||
)
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn set_chat_name(
|
||||
|
||||
@@ -7,7 +7,6 @@ use crate::blob::BlobObject;
|
||||
use crate::constants::DC_VERSION_STR;
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Error;
|
||||
use crate::job::*;
|
||||
use crate::stock::StockMessage;
|
||||
|
||||
@@ -113,7 +112,7 @@ impl Context {
|
||||
|
||||
/// Set the given config key.
|
||||
/// If `None` is passed as a value the value is cleared and set to the default if there is one.
|
||||
pub fn set_config(&self, key: Config, value: Option<&str>) -> Result<(), Error> {
|
||||
pub fn set_config(&self, key: Config, value: Option<&str>) -> crate::sql::Result<()> {
|
||||
match key {
|
||||
Config::Selfavatar if value.is_some() => {
|
||||
let blob = BlobObject::create_from_path(&self, value.unwrap())?;
|
||||
|
||||
@@ -141,7 +141,7 @@ pub enum VerifiedStatus {
|
||||
}
|
||||
|
||||
impl Contact {
|
||||
pub fn load_from_db(context: &Context, contact_id: u32) -> Result<Self> {
|
||||
pub fn load_from_db(context: &Context, contact_id: u32) -> crate::sql::Result<Self> {
|
||||
if contact_id == DC_CONTACT_ID_SELF {
|
||||
let contact = Contact {
|
||||
id: contact_id,
|
||||
@@ -691,7 +691,7 @@ impl Contact {
|
||||
}
|
||||
Err(err) => {
|
||||
error!(context, "delete_contact {} failed ({})", contact_id, err);
|
||||
return Err(err);
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -709,7 +709,7 @@ impl Contact {
|
||||
/// like "Me" in the selected language and the email address
|
||||
/// defined by dc_set_config().
|
||||
pub fn get_by_id(context: &Context, contact_id: u32) -> Result<Contact> {
|
||||
Contact::load_from_db(context, contact_id)
|
||||
Ok(Contact::load_from_db(context, contact_id)?)
|
||||
}
|
||||
|
||||
/// Get the ID of the contact.
|
||||
|
||||
24
src/error.rs
24
src/error.rs
@@ -2,18 +2,10 @@ use failure::Fail;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "Sqlite Error: {:?}", _0)]
|
||||
Sql(rusqlite::Error),
|
||||
#[fail(display = "Sqlite Connection Pool Error: {:?}", _0)]
|
||||
ConnectionPool(r2d2::Error),
|
||||
#[fail(display = "{:?}", _0)]
|
||||
Failure(failure::Error),
|
||||
#[fail(display = "Sqlite: Connection closed")]
|
||||
SqlNoConnection,
|
||||
#[fail(display = "Sqlite: Already open")]
|
||||
SqlAlreadyOpen,
|
||||
#[fail(display = "Sqlite: Failed to open")]
|
||||
SqlFailedToOpen,
|
||||
#[fail(display = "SQL error: {:?}", _0)]
|
||||
SqlError(#[cause] crate::sql::Error),
|
||||
#[fail(display = "{:?}", _0)]
|
||||
Io(std::io::Error),
|
||||
#[fail(display = "{:?}", _0)]
|
||||
@@ -40,9 +32,9 @@ pub enum Error {
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
impl From<rusqlite::Error> for Error {
|
||||
fn from(err: rusqlite::Error) -> Error {
|
||||
Error::Sql(err)
|
||||
impl From<crate::sql::Error> for Error {
|
||||
fn from(err: crate::sql::Error) -> Error {
|
||||
Error::SqlError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,12 +50,6 @@ impl From<failure::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<r2d2::Error> for Error {
|
||||
fn from(err: r2d2::Error) -> Error {
|
||||
Error::ConnectionPool(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Error {
|
||||
Error::Io(err)
|
||||
|
||||
49
src/imex.rs
49
src/imex.rs
@@ -462,7 +462,9 @@ fn import_backup(context: &Context, backup_to_import: impl AsRef<Path>) -> Resul
|
||||
|files| {
|
||||
for (processed_files_cnt, file) in files.enumerate() {
|
||||
let (file_name, file_blob) = file?;
|
||||
ensure!(!context.shall_stop_ongoing(), "received stop signal");
|
||||
if context.shall_stop_ongoing() {
|
||||
return Ok(false);
|
||||
}
|
||||
let mut permille = processed_files_cnt * 1000 / total_files_cnt;
|
||||
if permille < 10 {
|
||||
permille = 10
|
||||
@@ -476,26 +478,25 @@ fn import_backup(context: &Context, backup_to_import: impl AsRef<Path>) -> Resul
|
||||
}
|
||||
|
||||
let path_filename = context.get_blobdir().join(file_name);
|
||||
if dc_write_file(context, &path_filename, &file_blob).is_err() {
|
||||
bail!(
|
||||
"Storage full? Cannot write file {} with {} bytes.",
|
||||
path_filename.display(),
|
||||
file_blob.len(),
|
||||
);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
dc_write_file(context, &path_filename, &file_blob)?;
|
||||
}
|
||||
Ok(())
|
||||
Ok(true)
|
||||
},
|
||||
);
|
||||
|
||||
res.and_then(|_| {
|
||||
// only delete backup_blobs if all files were successfully extracted
|
||||
sql::execute(context, &context.sql, "DROP TABLE backup_blobs;", params![])?;
|
||||
sql::try_execute(context, &context.sql, "VACUUM;").ok();
|
||||
Ok(())
|
||||
})
|
||||
match res {
|
||||
Ok(all_files_extracted) => {
|
||||
if all_files_extracted {
|
||||
// only delete backup_blobs if all files were successfully extracted
|
||||
sql::execute(context, &context.sql, "DROP TABLE backup_blobs;", params![])?;
|
||||
sql::try_execute(context, &context.sql, "VACUUM;").ok();
|
||||
Ok(())
|
||||
} else {
|
||||
bail!("received stop signal");
|
||||
}
|
||||
}
|
||||
Err(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -553,7 +554,7 @@ fn export_backup(context: &Context, dir: impl AsRef<Path>) -> Result<()> {
|
||||
};
|
||||
dest_sql.close(context);
|
||||
|
||||
res
|
||||
Ok(res?)
|
||||
}
|
||||
|
||||
fn add_files_to_export(context: &Context, sql: &Sql) -> Result<()> {
|
||||
@@ -576,16 +577,15 @@ fn add_files_to_export(context: &Context, sql: &Sql) -> Result<()> {
|
||||
info!(context, "EXPORT: total_files_cnt={}", total_files_cnt);
|
||||
// scan directory, pass 2: copy files
|
||||
let dir_handle = std::fs::read_dir(&dir)?;
|
||||
sql.prepare(
|
||||
let exported_all_files = sql.prepare(
|
||||
"INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);",
|
||||
|mut stmt, _| {
|
||||
let mut processed_files_cnt = 0;
|
||||
for entry in dir_handle {
|
||||
let entry = entry?;
|
||||
ensure!(
|
||||
!context.shall_stop_ongoing(),
|
||||
"canceled during export-files"
|
||||
);
|
||||
if context.shall_stop_ongoing() {
|
||||
return Ok(false);
|
||||
}
|
||||
processed_files_cnt += 1;
|
||||
let permille = max(min(processed_files_cnt * 1000 / total_files_cnt, 990), 10);
|
||||
context.call_cb(Event::ImexProgress(permille));
|
||||
@@ -605,9 +605,10 @@ fn add_files_to_export(context: &Context, sql: &Sql) -> Result<()> {
|
||||
stmt.execute(params![name, buf])?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(true)
|
||||
},
|
||||
)?;
|
||||
ensure!(exported_all_files, "canceled during export-files");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -534,7 +534,7 @@ pub fn save(
|
||||
}
|
||||
Ok(newest_location_id)
|
||||
},
|
||||
)
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
||||
@@ -266,7 +266,7 @@ impl Message {
|
||||
|
||||
Ok(msg)
|
||||
},
|
||||
)
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn delete_from_db(context: &Context, msg_id: MsgId) {
|
||||
@@ -1256,7 +1256,7 @@ pub(crate) fn rfc724_mid_exists(
|
||||
|
||||
Ok((server_folder, server_uid, msg_id))
|
||||
},
|
||||
)
|
||||
).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn update_server_uid(
|
||||
|
||||
@@ -8,7 +8,6 @@ use crate::aheader::*;
|
||||
use crate::chat::*;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::error::*;
|
||||
use crate::key::*;
|
||||
use crate::sql::{self, Sql};
|
||||
|
||||
@@ -385,7 +384,7 @@ impl<'a> Peerstate<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_to_db(&self, sql: &Sql, create: bool) -> Result<()> {
|
||||
pub fn save_to_db(&self, sql: &Sql, create: bool) -> crate::sql::Result<()> {
|
||||
if create {
|
||||
sql::execute(
|
||||
self.context,
|
||||
|
||||
58
src/sql.rs
58
src/sql.rs
@@ -1,5 +1,7 @@
|
||||
//! # SQLite wrapper
|
||||
|
||||
use failure::Fail;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Duration;
|
||||
@@ -11,10 +13,53 @@ use crate::chat::update_saved_messages_icon;
|
||||
use crate::constants::ShowEmails;
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::param::*;
|
||||
use crate::peerstate::*;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "Sqlite Error: {:?}", _0)]
|
||||
Sql(#[cause] rusqlite::Error),
|
||||
#[fail(display = "Sqlite Connection Pool Error: {:?}", _0)]
|
||||
ConnectionPool(#[cause] r2d2::Error),
|
||||
#[fail(display = "Sqlite: Connection closed")]
|
||||
SqlNoConnection,
|
||||
#[fail(display = "Sqlite: Already open")]
|
||||
SqlAlreadyOpen,
|
||||
#[fail(display = "Sqlite: Failed to open")]
|
||||
SqlFailedToOpen,
|
||||
#[fail(display = "{:?}", _0)]
|
||||
Io(#[cause] std::io::Error),
|
||||
#[fail(display = "{:?}", _0)]
|
||||
BlobError(#[cause] crate::blob::BlobError),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
impl From<rusqlite::Error> for Error {
|
||||
fn from(err: rusqlite::Error) -> Error {
|
||||
Error::Sql(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<r2d2::Error> for Error {
|
||||
fn from(err: r2d2::Error) -> Error {
|
||||
Error::ConnectionPool(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Error {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::blob::BlobError> for Error {
|
||||
fn from(err: crate::blob::BlobError) -> Error {
|
||||
Error::BlobError(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper around the underlying Sqlite3 object.
|
||||
#[derive(DebugStub)]
|
||||
pub struct Sql {
|
||||
@@ -47,7 +92,7 @@ impl Sql {
|
||||
pub fn open(&self, context: &Context, dbfile: &std::path::Path, readonly: bool) -> bool {
|
||||
match open(context, self, dbfile, readonly) {
|
||||
Ok(_) => true,
|
||||
Err(Error::SqlAlreadyOpen) => false,
|
||||
Err(crate::error::Error::SqlError(Error::SqlAlreadyOpen)) => false,
|
||||
Err(_) => {
|
||||
self.close(context);
|
||||
false
|
||||
@@ -321,14 +366,14 @@ fn open(
|
||||
sql: &Sql,
|
||||
dbfile: impl AsRef<std::path::Path>,
|
||||
readonly: bool,
|
||||
) -> Result<()> {
|
||||
) -> crate::error::Result<()> {
|
||||
if sql.is_open() {
|
||||
error!(
|
||||
context,
|
||||
"Cannot open, database \"{:?}\" already opened.",
|
||||
dbfile.as_ref(),
|
||||
);
|
||||
return Err(Error::SqlAlreadyOpen);
|
||||
return Err(Error::SqlAlreadyOpen.into());
|
||||
}
|
||||
|
||||
let mut open_flags = OpenFlags::SQLITE_OPEN_NO_MUTEX;
|
||||
@@ -345,7 +390,8 @@ fn open(
|
||||
.min_idle(Some(2))
|
||||
.max_size(10)
|
||||
.connection_timeout(std::time::Duration::new(60, 0))
|
||||
.build(mgr)?;
|
||||
.build(mgr)
|
||||
.map_err(Error::ConnectionPool)?;
|
||||
|
||||
{
|
||||
*sql.pool.write().unwrap() = Some(pool);
|
||||
@@ -477,7 +523,7 @@ fn open(
|
||||
dbfile.as_ref(),
|
||||
);
|
||||
// cannot create the tables - maybe we cannot write?
|
||||
return Err(Error::SqlFailedToOpen);
|
||||
return Err(Error::SqlFailedToOpen.into());
|
||||
} else {
|
||||
sql.set_raw_config_int(context, "dbversion", 0)?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user