diff --git a/rslib/src/storage/deckconfig/mod.rs b/rslib/src/storage/deckconfig/mod.rs index 6ef2031a1..5ea57aae3 100644 --- a/rslib/src/storage/deckconfig/mod.rs +++ b/rslib/src/storage/deckconfig/mod.rs @@ -15,9 +15,11 @@ use crate::deckconfig::DeckConfigId; use crate::deckconfig::DeckConfigInner; use crate::prelude::*; -fn row_to_deckconf(row: &Row) -> Result { +fn row_to_deckconf(row: &Row, fix_invalid: bool) -> Result { let mut config = DeckConfigInner::decode(row.get_ref_unwrap(4).as_blob()?)?; - config.ensure_values_valid(); + if fix_invalid { + config.ensure_values_valid(); + } Ok(DeckConfig { id: row.get(0)?, name: row.get(1)?, @@ -31,14 +33,22 @@ impl SqliteStorage { pub(crate) fn all_deck_config(&self) -> Result> { self.db .prepare_cached(include_str!("get.sql"))? - .query_and_then([], row_to_deckconf)? + .query_and_then([], |row| row_to_deckconf(row, true))? + .collect() + } + + /// Does not cap values to those expected by the latest schema. + pub(crate) fn all_deck_config_for_schema16_upgrade(&self) -> Result> { + self.db + .prepare_cached(include_str!("get.sql"))? + .query_and_then([], |row| row_to_deckconf(row, false))? .collect() } pub(crate) fn get_deck_config_map(&self) -> Result> { self.db .prepare_cached(include_str!("get.sql"))? - .query_and_then([], row_to_deckconf)? + .query_and_then([], |row| row_to_deckconf(row, true))? .map(|res| res.map(|d| (d.id, d))) .collect() } @@ -46,7 +56,7 @@ impl SqliteStorage { pub(crate) fn get_deck_config(&self, dcid: DeckConfigId) -> Result> { self.db .prepare_cached(concat!(include_str!("get.sql"), " where id = ?"))? - .query_and_then(params![dcid], row_to_deckconf)? + .query_and_then(params![dcid], |row| row_to_deckconf(row, true))? .next() .transpose() } @@ -217,7 +227,7 @@ impl SqliteStorage { pub(super) fn upgrade_deck_conf_to_schema16(&self, server: bool) -> Result<()> { let mut invalid_configs = vec![]; - for mut conf in self.all_deck_config()? { + for mut conf in self.all_deck_config_for_schema16_upgrade()? { // schema 16 changed starting ease of 250 to 2.5 conf.inner.initial_ease /= 100.0; // new deck configs created with schema 15 had the wrong diff --git a/rslib/src/storage/upgrades/mod.rs b/rslib/src/storage/upgrades/mod.rs index 12ac1593c..bae147015 100644 --- a/rslib/src/storage/upgrades/mod.rs +++ b/rslib/src/storage/upgrades/mod.rs @@ -78,6 +78,9 @@ impl SqliteStorage { #[cfg(test)] mod test { use super::*; + use crate::collection::CollectionBuilder; + use crate::io::new_tempfile; + use crate::prelude::*; #[test] #[allow(clippy::assertions_on_constants)] @@ -87,4 +90,25 @@ mod test { "must implement SqliteStorage::downgrade_to(SchemaVersion::V18)" ); } + + #[test] + fn valid_ease_factor_survives_upgrade_roundtrip() -> Result<()> { + let tempfile = new_tempfile()?; + let mut col = CollectionBuilder::default() + .set_collection_path(tempfile.path()) + .build()?; + let nt = col.get_notetype_by_name("Basic")?.unwrap(); + let mut note = nt.new_note(); + col.add_note(&mut note, DeckId(1))?; + col.storage + .db + .execute("update cards set factor = 1400", [])?; + col.close(Some(SchemaVersion::V11))?; + let col = CollectionBuilder::default() + .set_collection_path(tempfile.path()) + .build()?; + let card = &col.storage.get_all_cards()[0]; + assert_eq!(card.ease_factor, 1400); + Ok(()) + } }