From e1899152be3212c3e123bbf3e9a8094572a9bf6d Mon Sep 17 00:00:00 2001 From: RumovZ Date: Sun, 10 Apr 2022 09:22:41 +0200 Subject: [PATCH] Fix importing cards/revlog Card ids are manually uniquified. --- .../src/import_export/package/apkg/import.rs | 24 ++++++++++++++----- rslib/src/storage/card/mod.rs | 7 ++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/rslib/src/import_export/package/apkg/import.rs b/rslib/src/import_export/package/apkg/import.rs index 7bf339ad8..0f858a43e 100644 --- a/rslib/src/import_export/package/apkg/import.rs +++ b/rslib/src/import_export/package/apkg/import.rs @@ -53,7 +53,8 @@ struct Context<'a> { /// Source notes that cannot be imported, because notes with the same guid /// exist in the target, but their notetypes don't match. conflicting_notes: HashSet, - added_cards: HashSet, + remapped_cards: HashMap, + existing_cards: HashSet, normalize_notes: bool, } @@ -133,6 +134,7 @@ impl<'a> Context<'a> { let usn = target_col.usn()?; let normalize_notes = target_col.get_config_bool(BoolKey::NormalizeNoteText); let existing_notes = target_col.storage.get_all_note_ids()?; + let existing_cards = target_col.storage.get_all_card_ids()?; Ok(Self { target_col, archive, @@ -144,7 +146,8 @@ impl<'a> Context<'a> { remapped_notes: HashMap::new(), existing_notes, remapped_decks: HashMap::new(), - added_cards: HashSet::new(), + remapped_cards: HashMap::new(), + existing_cards, used_media_entries: HashMap::new(), normalize_notes, }) @@ -422,9 +425,9 @@ impl<'a> Context<'a> { fn add_card(&mut self, card: &mut Card) -> Result<()> { card.usn = self.usn; - if self.target_col.add_card_if_unique_undoable(card)? { - self.added_cards.insert(card.id); - } + self.uniquify_card_id(card); + self.target_col.add_card_if_unique_undoable(card)?; + self.existing_cards.insert(card.id); Ok(()) } @@ -434,6 +437,14 @@ impl<'a> Context<'a> { } } + fn uniquify_card_id(&mut self, card: &mut Card) { + let original = card.id; + while self.existing_cards.contains(&card.id) { + card.id.0 += 999; + } + self.remapped_cards.insert(original, card.id); + } + fn remap_deck_id(&self, card: &mut Card) { if let Some(did) = self.remapped_decks.get(&card.deck_id) { card.deck_id = *did; @@ -442,7 +453,8 @@ impl<'a> Context<'a> { fn import_revlog(&mut self) -> Result<()> { for mut entry in mem::take(&mut self.data.revlog) { - if self.added_cards.contains(&entry.cid) { + if let Some(cid) = self.remapped_cards.get(&entry.cid) { + entry.cid = *cid; entry.usn = self.usn; self.target_col.add_revlog_entry_if_unique_undoable(entry)?; } diff --git a/rslib/src/storage/card/mod.rs b/rslib/src/storage/card/mod.rs index 0d3352c42..906894007 100644 --- a/rslib/src/storage/card/mod.rs +++ b/rslib/src/storage/card/mod.rs @@ -428,6 +428,13 @@ impl super::SqliteStorage { .collect() } + pub(crate) fn get_all_card_ids(&self) -> Result> { + self.db + .prepare("SELECT id FROM cards")? + .query_and_then([], |row| Ok(row.get(0)?))? + .collect() + } + pub(crate) fn all_cards_as_nid_and_ord(&self) -> Result> { self.db .prepare("SELECT nid, ord FROM cards")?