diff --git a/rslib/src/deckconfig/update.rs b/rslib/src/deckconfig/update.rs index 4427a6188..e5573c538 100644 --- a/rslib/src/deckconfig/update.rs +++ b/rslib/src/deckconfig/update.rs @@ -19,6 +19,7 @@ use crate::prelude::*; use crate::scheduler::fsrs::memory_state::UpdateMemoryStateRequest; use crate::search::JoinSearches; use crate::search::SearchNode; +use crate::storage::comma_separated_ids; #[derive(Debug, Clone)] pub struct UpdateDeckConfigsRequest { @@ -164,7 +165,7 @@ impl Collection { let usn = self.usn()?; let today = self.timing_today()?.days_elapsed; let selected_config = req.configs.last().unwrap(); - let mut decks_needing_memory_recompute: HashMap> = + let mut decks_needing_memory_recompute: HashMap> = Default::default(); let fsrs_toggled = self.get_config_bool(BoolKey::Fsrs) != req.fsrs; if fsrs_toggled { @@ -216,7 +217,7 @@ impl Collection { decks_needing_memory_recompute .entry(current_config_id) .or_default() - .push(SearchNode::DeckIdWithoutChildren(deck_id)); + .push(deck_id); } self.adjust_remaining_steps_in_deck(deck_id, previous_config, current_config, usn)?; @@ -224,7 +225,7 @@ impl Collection { } if !decks_needing_memory_recompute.is_empty() { - let input: Vec<(Option, Vec)> = + let input: Vec<(Option, SearchNode)> = decks_needing_memory_recompute .into_iter() .map(|(conf_id, search)| { @@ -240,7 +241,10 @@ impl Collection { None } }); - Ok((weights, search)) + Ok(( + weights, + SearchNode::DeckIdsWithoutChildren(comma_separated_ids(&search)), + )) }) .collect::>()?; self.update_memory_state(input)?; diff --git a/rslib/src/scheduler/fsrs/memory_state.rs b/rslib/src/scheduler/fsrs/memory_state.rs index 37c5ef8d1..6ec534169 100644 --- a/rslib/src/scheduler/fsrs/memory_state.rs +++ b/rslib/src/scheduler/fsrs/memory_state.rs @@ -16,7 +16,6 @@ use crate::revlog::RevlogReviewKind; use crate::scheduler::fsrs::weights::single_card_revlog_to_items; use crate::scheduler::fsrs::weights::Weights; use crate::scheduler::states::fuzz::with_review_fuzz; -use crate::search::JoinSearches; use crate::search::Negated; use crate::search::SearchNode; use crate::search::StateKind; @@ -43,13 +42,13 @@ impl Collection { /// memory state should be removed. pub(crate) fn update_memory_state( &mut self, - entries: Vec<(Option, Vec)>, + entries: Vec<(Option, SearchNode)>, ) -> Result<()> { let timing = self.timing_today()?; let usn = self.usn()?; for (req, search) in entries { - let search = SearchBuilder::any(search.into_iter()) - .and(SearchNode::State(StateKind::New).negated()); + let search = + SearchBuilder::all([search.into(), SearchNode::State(StateKind::New).negated()]); let revlog = self.revlog_for_srs(search)?; let reschedule = req.as_ref().map(|e| e.reschedule).unwrap_or_default(); let last_reviews = if reschedule { diff --git a/rslib/src/scheduler/new.rs b/rslib/src/scheduler/new.rs index 7dc2a346b..e50bda328 100644 --- a/rslib/src/scheduler/new.rs +++ b/rslib/src/scheduler/new.rs @@ -281,7 +281,7 @@ impl Collection { usn: Usn, ) -> Result { let cids = self.search_cards( - SearchNode::DeckIdWithoutChildren(deck).and(StateKind::New), + SearchNode::DeckIdsWithoutChildren(deck.to_string()).and(StateKind::New), SortMode::NoOrder, )?; self.sort_cards_inner(&cids, 1, 1, order.into(), false, usn) diff --git a/rslib/src/search/builder.rs b/rslib/src/search/builder.rs index 198bf4b29..452f4d832 100644 --- a/rslib/src/search/builder.rs +++ b/rslib/src/search/builder.rs @@ -11,6 +11,7 @@ use super::SearchNode; use super::StateKind; use super::TemplateKind; use crate::prelude::*; +use crate::storage::comma_separated_ids; use crate::text::escape_anki_wildcards_for_search_node; pub trait Negated { @@ -123,7 +124,7 @@ impl SearchBuilder { /// Construct [SearchBuilder] matching any given deck, excluding children. pub fn from_decks(decks: &[DeckId]) -> Self { - Self::any(decks.iter().copied().map(SearchNode::DeckIdWithoutChildren)) + SearchNode::DeckIdsWithoutChildren(comma_separated_ids(decks)).into() } /// Construct [SearchBuilder] matching learning, but not relearning cards. @@ -160,7 +161,7 @@ impl SearchNode { if with_children { Self::DeckIdWithChildren(did.into()) } else { - Self::DeckIdWithoutChildren(did.into()) + Self::DeckIdsWithoutChildren(did.into().to_string()) } } diff --git a/rslib/src/search/parser.rs b/rslib/src/search/parser.rs index da989b07b..8af7991b3 100644 --- a/rslib/src/search/parser.rs +++ b/rslib/src/search/parser.rs @@ -60,8 +60,8 @@ pub enum SearchNode { EditedInDays(u32), CardTemplate(TemplateKind), Deck(String), - /// Matches cards in a single deck (original_deck_id is not checked). - DeckIdWithoutChildren(DeckId), + /// Matches cards in a list of decks (original_deck_id is not checked). + DeckIdsWithoutChildren(String), /// Matches cards in a deck or its children (original_deck_id is not /// checked). DeckIdWithChildren(DeckId), @@ -346,7 +346,7 @@ fn search_node_for_text_with_argument<'a>( "introduced" => parse_introduced(val)?, "rated" => parse_rated(val)?, "is" => parse_state(val)?, - "did" => parse_did(val)?, + "did" => SearchNode::DeckIdsWithoutChildren(check_id_list(val, key)?.into()), "mid" => parse_mid(val)?, "nid" => SearchNode::NoteIds(check_id_list(val, key)?.into()), "cid" => SearchNode::CardIds(check_id_list(val, key)?.into()), @@ -614,10 +614,6 @@ fn parse_state(s: &str) -> ParseResult { })) } -fn parse_did(s: &str) -> ParseResult { - parse_i64(s, "did:").map(|n| SearchNode::DeckIdWithoutChildren(n.into())) -} - fn parse_mid(s: &str) -> ParseResult { parse_i64(s, "mid:").map(|n| SearchNode::NotetypeId(n.into())) } diff --git a/rslib/src/search/sqlwriter.rs b/rslib/src/search/sqlwriter.rs index fd1456f5d..2d9ab5731 100644 --- a/rslib/src/search/sqlwriter.rs +++ b/rslib/src/search/sqlwriter.rs @@ -160,8 +160,8 @@ impl SqlWriter<'_> { SearchNode::NotetypeId(ntid) => { write!(self.sql, "n.mid = {}", ntid).unwrap(); } - SearchNode::DeckIdWithoutChildren(did) => { - write!(self.sql, "c.did = {}", did).unwrap(); + SearchNode::DeckIdsWithoutChildren(dids) => { + write!(self.sql, "c.did in ({})", dids).unwrap(); } SearchNode::DeckIdWithChildren(did) => self.write_deck_id_with_children(*did)?, SearchNode::Notetype(notetype) => self.write_notetype(&norm(notetype)), @@ -965,7 +965,7 @@ impl SearchNode { SearchNode::AddedInDays(_) => RequiredTable::Cards, SearchNode::IntroducedInDays(_) => RequiredTable::Cards, SearchNode::Deck(_) => RequiredTable::Cards, - SearchNode::DeckIdWithoutChildren(_) => RequiredTable::Cards, + SearchNode::DeckIdsWithoutChildren(_) => RequiredTable::Cards, SearchNode::DeckIdWithChildren(_) => RequiredTable::Cards, SearchNode::Rated { .. } => RequiredTable::Cards, SearchNode::State(_) => RequiredTable::Cards, @@ -973,6 +973,7 @@ impl SearchNode { SearchNode::CardIds(_) => RequiredTable::Cards, SearchNode::Property { .. } => RequiredTable::Cards, SearchNode::CustomData { .. } => RequiredTable::Cards, + SearchNode::Preset(_) => RequiredTable::Cards, SearchNode::UnqualifiedText(_) => RequiredTable::Notes, SearchNode::SingleField { .. } => RequiredTable::Notes, @@ -989,7 +990,6 @@ impl SearchNode { SearchNode::WholeCollection => RequiredTable::CardsOrNotes, SearchNode::CardTemplate(_) => RequiredTable::CardsAndNotes, - SearchNode::Preset(_) => RequiredTable::Cards, } } } diff --git a/rslib/src/search/writer.rs b/rslib/src/search/writer.rs index cc79c3a0e..687dd150a 100644 --- a/rslib/src/search/writer.rs +++ b/rslib/src/search/writer.rs @@ -6,7 +6,6 @@ use std::mem; use lazy_static::lazy_static; use regex::Regex; -use crate::decks::DeckId as DeckIdType; use crate::notetype::NotetypeId as NotetypeIdType; use crate::prelude::*; use crate::search::parser::parse; @@ -69,7 +68,7 @@ fn write_search_node(node: &SearchNode) -> String { IntroducedInDays(u) => format!("introduced:{}", u), CardTemplate(t) => write_template(t), Deck(s) => maybe_quote(&format!("deck:{}", s)), - DeckIdWithoutChildren(DeckIdType(i)) => format!("did:{}", i), + DeckIdsWithoutChildren(s) => format!("did:{}", s), // not exposed on the GUI end DeckIdWithChildren(_) => "".to_string(), NotetypeId(NotetypeIdType(i)) => format!("mid:{}", i),