switch DbError to tuple type
This commit is contained in:
parent
1704f7fe80
commit
a250464309
@ -4,7 +4,7 @@
|
||||
use crate::{
|
||||
collection::Collection,
|
||||
config::SchedulerVersion,
|
||||
error::{AnkiError, DbErrorKind, Result},
|
||||
error::{AnkiError, DbError, DbErrorKind, Result},
|
||||
i18n::I18n,
|
||||
notetype::{
|
||||
all_stock_notetypes, AlreadyGeneratedCardInfo, CardGenContext, Notetype, NotetypeId,
|
||||
@ -90,10 +90,10 @@ impl Collection {
|
||||
debug!(self.log, "quick check");
|
||||
if self.storage.quick_check_corrupt() {
|
||||
debug!(self.log, "quick check failed");
|
||||
return Err(AnkiError::DbError {
|
||||
info: self.tr.database_check_corrupt().into(),
|
||||
kind: DbErrorKind::Corrupt,
|
||||
});
|
||||
return Err(AnkiError::db_error(
|
||||
self.tr.database_check_corrupt(),
|
||||
DbErrorKind::Corrupt,
|
||||
));
|
||||
}
|
||||
|
||||
progress_fn(DatabaseCheckProgress::Optimize, false);
|
||||
@ -289,10 +289,10 @@ impl Collection {
|
||||
match self.storage.get_note(nid) {
|
||||
Ok(note) => Ok(note.unwrap()),
|
||||
Err(err) => match err {
|
||||
AnkiError::DbError {
|
||||
AnkiError::DbError(DbError {
|
||||
kind: DbErrorKind::Utf8,
|
||||
..
|
||||
} => {
|
||||
}) => {
|
||||
// fix note then fetch again
|
||||
self.storage.fix_invalid_utf8_in_note(nid)?;
|
||||
out.invalid_utf8 += 1;
|
||||
|
@ -1,11 +1,18 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use anki_i18n::I18n;
|
||||
use rusqlite::{types::FromSqlError, Error};
|
||||
use std::str::Utf8Error;
|
||||
|
||||
use super::AnkiError;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct DbError {
|
||||
pub info: String,
|
||||
pub kind: DbErrorKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DbErrorKind {
|
||||
FileTooNew,
|
||||
@ -17,23 +24,32 @@ pub enum DbErrorKind {
|
||||
Other,
|
||||
}
|
||||
|
||||
impl AnkiError {
|
||||
pub(crate) fn db_error(info: impl Into<String>, kind: DbErrorKind) -> Self {
|
||||
AnkiError::DbError(DbError {
|
||||
info: info.into(),
|
||||
kind,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for AnkiError {
|
||||
fn from(err: Error) -> Self {
|
||||
if let Error::SqliteFailure(error, Some(reason)) = &err {
|
||||
if error.code == rusqlite::ErrorCode::DatabaseBusy {
|
||||
return AnkiError::DbError {
|
||||
return AnkiError::DbError(DbError {
|
||||
info: "".to_string(),
|
||||
kind: DbErrorKind::Locked,
|
||||
};
|
||||
});
|
||||
}
|
||||
if reason.contains("regex parse error") {
|
||||
return AnkiError::InvalidRegex(reason.to_owned());
|
||||
}
|
||||
}
|
||||
AnkiError::DbError {
|
||||
AnkiError::DbError(DbError {
|
||||
info: format!("{:?}", err),
|
||||
kind: DbErrorKind::Other,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,15 +57,26 @@ impl From<FromSqlError> for AnkiError {
|
||||
fn from(err: FromSqlError) -> Self {
|
||||
if let FromSqlError::Other(ref err) = err {
|
||||
if let Some(_err) = err.downcast_ref::<Utf8Error>() {
|
||||
return AnkiError::DbError {
|
||||
return AnkiError::DbError(DbError {
|
||||
info: "".to_string(),
|
||||
kind: DbErrorKind::Utf8,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
AnkiError::DbError {
|
||||
AnkiError::DbError(DbError {
|
||||
info: format!("{:?}", err),
|
||||
kind: DbErrorKind::Other,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl DbError {
|
||||
pub fn localized_description(&self, _tr: &I18n) -> String {
|
||||
match self.kind {
|
||||
DbErrorKind::Corrupt => self.info.clone(),
|
||||
// fixme: i18n
|
||||
DbErrorKind::Locked => "Anki already open, or media currently syncing.".into(),
|
||||
_ => format!("{:?}", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ mod network;
|
||||
mod search;
|
||||
|
||||
pub use {
|
||||
db::DbErrorKind,
|
||||
db::{DbError, DbErrorKind},
|
||||
network::{NetworkError, NetworkErrorKind, SyncError, SyncErrorKind},
|
||||
search::{ParseError, SearchErrorKind},
|
||||
};
|
||||
@ -23,7 +23,7 @@ pub enum AnkiError {
|
||||
TemplateError { info: String },
|
||||
TemplateSaveError { ordinal: usize },
|
||||
IoError { info: String },
|
||||
DbError { info: String, kind: DbErrorKind },
|
||||
DbError(DbError),
|
||||
NetworkError(NetworkError),
|
||||
SyncError(SyncError),
|
||||
JsonError { info: String },
|
||||
@ -52,10 +52,6 @@ impl AnkiError {
|
||||
AnkiError::InvalidInput { info: s.into() }
|
||||
}
|
||||
|
||||
pub(crate) fn server_message<S: Into<String>>(msg: S) -> AnkiError {
|
||||
AnkiError::sync_error(msg, SyncErrorKind::ServerMessage)
|
||||
}
|
||||
|
||||
pub fn localized_description(&self, tr: &I18n) -> String {
|
||||
match self {
|
||||
AnkiError::SyncError(err) => err.localized_description(tr),
|
||||
@ -67,11 +63,7 @@ impl AnkiError {
|
||||
AnkiError::TemplateSaveError { ordinal } => tr
|
||||
.card_templates_invalid_template_number(ordinal + 1)
|
||||
.into(),
|
||||
AnkiError::DbError { info, kind } => match kind {
|
||||
DbErrorKind::Corrupt => info.clone(),
|
||||
DbErrorKind::Locked => "Anki already open, or media currently syncing.".into(),
|
||||
_ => format!("{:?}", self),
|
||||
},
|
||||
AnkiError::DbError(err) => err.localized_description(tr),
|
||||
AnkiError::SearchError(kind) => kind.localized_description(&tr),
|
||||
AnkiError::InvalidInput { info } => {
|
||||
if info.is_empty() {
|
||||
|
@ -47,6 +47,10 @@ impl AnkiError {
|
||||
kind,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn server_message<S: Into<String>>(msg: S) -> AnkiError {
|
||||
AnkiError::sync_error(msg, SyncErrorKind::ServerMessage)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for AnkiError {
|
||||
|
@ -360,12 +360,9 @@ where
|
||||
self.fire_progress_cb()?;
|
||||
}
|
||||
let mut note = self.ctx.storage.get_note(nid)?.unwrap();
|
||||
let nt = notetypes
|
||||
.get(¬e.notetype_id)
|
||||
.ok_or_else(|| AnkiError::DbError {
|
||||
info: "missing note type".to_string(),
|
||||
kind: DbErrorKind::MissingEntity,
|
||||
})?;
|
||||
let nt = notetypes.get(¬e.notetype_id).ok_or_else(|| {
|
||||
AnkiError::db_error("missing note type", DbErrorKind::MissingEntity)
|
||||
})?;
|
||||
if fix_and_extract_media_refs(
|
||||
&mut note,
|
||||
&mut referenced_files,
|
||||
|
@ -27,9 +27,11 @@ fn row_to_deck(row: &Row) -> Result<Deck> {
|
||||
mtime_secs: row.get(2)?,
|
||||
usn: row.get(3)?,
|
||||
common,
|
||||
kind: kind.kind.ok_or_else(|| AnkiError::DbError {
|
||||
kind: DbErrorKind::MissingEntity,
|
||||
info: format!("invalid deck kind: {}", id),
|
||||
kind: kind.kind.ok_or_else(|| {
|
||||
AnkiError::db_error(
|
||||
format!("invalid deck kind: {}", id),
|
||||
DbErrorKind::MissingEntity,
|
||||
)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
@ -382,10 +384,7 @@ impl SqliteStorage {
|
||||
Ok(v)
|
||||
})?
|
||||
.next()
|
||||
.ok_or_else(|| AnkiError::DbError {
|
||||
info: "col table empty".to_string(),
|
||||
kind: DbErrorKind::MissingEntity,
|
||||
})??;
|
||||
.ok_or_else(|| AnkiError::db_error("col table empty", DbErrorKind::MissingEntity))??;
|
||||
Ok(decks)
|
||||
}
|
||||
|
||||
|
@ -393,10 +393,7 @@ and ord in ",
|
||||
},
|
||||
)?
|
||||
.next()
|
||||
.ok_or_else(|| AnkiError::DbError {
|
||||
info: "col table empty".to_string(),
|
||||
kind: DbErrorKind::MissingEntity,
|
||||
})??;
|
||||
.ok_or_else(|| AnkiError::db_error("col table empty", DbErrorKind::MissingEntity))??;
|
||||
Ok(notetypes)
|
||||
}
|
||||
|
||||
|
@ -153,10 +153,7 @@ impl SqliteStorage {
|
||||
_ => None,
|
||||
};
|
||||
if let Some(kind) = err {
|
||||
return Err(AnkiError::DbError {
|
||||
info: "".to_string(),
|
||||
kind,
|
||||
});
|
||||
return Err(AnkiError::db_error("", kind));
|
||||
}
|
||||
|
||||
let upgrade = ver != SCHEMA_MAX_VERSION;
|
||||
|
Loading…
Reference in New Issue
Block a user