Keep source id of imported cards (or skip)

This commit is contained in:
RumovZ 2022-04-09 09:49:36 +02:00
parent 726438d1c5
commit a0604a2e51
4 changed files with 89 additions and 7 deletions

View file

@ -35,6 +35,14 @@ impl Collection {
Ok(())
}
pub(crate) fn add_card_if_unique_undoable(&mut self, card: &Card) -> Result<bool> {
let added = self.storage.add_card_if_unique(card)?;
if added {
self.save_undo(UndoableCardChange::Added(Box::new(card.clone())));
}
Ok(added)
}
pub(super) fn update_card_undoable(&mut self, card: &mut Card, original: Card) -> Result<()> {
if card.id.0 == 0 {
return Err(AnkiError::invalid_input("card id not set"));

View file

@ -41,7 +41,6 @@ struct Context<'a> {
remapped_notes: HashMap<NoteId, NoteId>,
remapped_decks: HashMap<DeckId, DeckId>,
remapped_deck_configs: HashMap<DeckConfigId, DeckConfigId>,
remapped_cards: HashMap<CardId, CardId>,
data: ExchangeData,
usn: Usn,
/// Map of source media files, that do not already exist in the target.
@ -52,6 +51,7 @@ 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<NoteId>,
added_cards: HashSet<CardId>,
normalize_notes: bool,
}
@ -139,7 +139,7 @@ impl<'a> Context<'a> {
remapped_notes: HashMap::new(),
remapped_decks: HashMap::new(),
remapped_deck_configs: HashMap::new(),
remapped_cards: HashMap::new(),
added_cards: HashSet::new(),
used_media_entries: HashMap::new(),
normalize_notes,
})
@ -405,9 +405,15 @@ impl<'a> Context<'a> {
self.remap_deck_id(&mut card);
// TODO: adjust collection-relative due times
// TODO: remove cards from filtered decks
let old_id = mem::take(&mut card.id);
self.target_col.add_card(&mut card)?;
self.remapped_cards.insert(old_id, card.id);
self.add_card(&mut card)?;
}
Ok(())
}
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);
}
Ok(())
}
@ -426,8 +432,7 @@ impl<'a> Context<'a> {
fn import_revlog(&mut self) -> Result<()> {
for mut entry in mem::take(&mut self.data.revlog) {
if let Some(cid) = self.remapped_cards.get(&entry.cid) {
entry.cid = *cid;
if self.added_cards.contains(&entry.cid) {
entry.usn = self.usn;
self.target_col.add_revlog_entry_undoable(entry)?;
}

View file

@ -0,0 +1,41 @@
INSERT
OR IGNORE INTO cards (
id,
nid,
did,
ord,
mod,
usn,
type,
queue,
due,
ivl,
factor,
reps,
lapses,
left,
odue,
odid,
flags,
data
)
VALUES (
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?
)

View file

@ -145,6 +145,34 @@ impl super::SqliteStorage {
Ok(())
}
/// Add card if id is unique. True if card was added.
pub(crate) fn add_card_if_unique(&self, card: &Card) -> Result<bool> {
self.db
.prepare_cached(include_str!("add_card_if_unique.sql"))?
.execute(params![
card.id,
card.note_id,
card.deck_id,
card.template_idx,
card.mtime,
card.usn,
card.ctype as u8,
card.queue as i8,
card.due,
card.interval,
card.ease_factor,
card.reps,
card.lapses,
card.remaining_steps,
card.original_due,
card.original_deck_id,
card.flags,
CardData::from_card(card),
])
.map(|n_rows| n_rows == 1)
.map_err(Into::into)
}
/// Add or update card, using the provided ID. Used for syncing & undoing.
pub(crate) fn add_or_update_card(&self, card: &Card) -> Result<()> {
let mut stmt = self.db.prepare_cached(include_str!("add_or_update.sql"))?;