diff --git a/rslib/src/search/sqlwriter.rs b/rslib/src/search/sqlwriter.rs index dc61f9b79..5481b2c67 100644 --- a/rslib/src/search/sqlwriter.rs +++ b/rslib/src/search/sqlwriter.rs @@ -116,6 +116,7 @@ impl SqlWriter<'_> { fn write_search_node_to_sql(&mut self, node: &SearchNode) -> Result<()> { use normalize_to_nfc as norm; + use std::cmp::max; match node { // note fields related SearchNode::UnqualifiedText(text) => self.write_unqualified(&self.norm_note(text)), @@ -144,7 +145,7 @@ impl SqlWriter<'_> { write!(self.sql, "c.did = {}", did).unwrap(); } SearchNode::NoteType(notetype) => self.write_note_type(&norm(notetype))?, - SearchNode::Rated { days, ease } => self.write_rated(*days, ease)?, + SearchNode::Rated { days, ease } => self.write_rated(*days, ease, "<")?, SearchNode::Tag(tag) => self.write_tag(&norm(tag))?, SearchNode::State(state) => self.write_state(state)?, @@ -214,9 +215,11 @@ impl SqlWriter<'_> { Ok(()) } - fn write_rated(&mut self, days: u32, ease: &EaseKind) -> Result<()> { + fn write_rated(&mut self, days: u32, ease: &EaseKind, op: &str) -> Result<()> { let today_cutoff = self.col.timing_today()?.next_day_at; let target_cutoff_ms = (today_cutoff - 86_400 * i64::from(days)) * 1_000; + let day_before_cutoff_ms = (today_cutoff - 86_400 * (days)) * 1_000; + write!( self.sql, "c.id in (select cid from revlog where id>{}", @@ -224,6 +227,17 @@ impl SqlWriter<'_> { ) .unwrap(); + // We use positive numbers for negative offsets + // which is why operators are reversed + match op { + "<" => write!(self.sql, "{} {}", ">", target_cutoff_ms), + ">" => write!(self.sql, "{} {}", "<", day_before_cutoff_ms), + "<=" => write!(self.sql, "{} {}", ">", day_before_cutoff_ms), + ">=" => write!(self.sql, "{} {}", "<", target_cutoff_ms), + "=" => write!(self.sql, "between {} and {}", target_cutoff_ms, day_before_cutoff_ms), + _ /* "!=" */ => write!(self.sql, "not between {} and {}", target_cutoff_ms, day_before_cutoff_ms), + }.unwrap(); + match ease { EaseKind::AnswerButton(u) => write!(self.sql, " and ease = {})", u), EaseKind::AnyAnswerButton => write!(self.sql, " and ease > 0)"), @@ -255,7 +269,7 @@ impl SqlWriter<'_> { previewrepeat = CardQueue::PreviewRepeat as i8, cutoff = timing.next_day_at, days = days - ) + ).unwrap() } PropertyKind::Position(pos) => { write!( @@ -264,19 +278,17 @@ impl SqlWriter<'_> { t = CardType::New as u8, op = op, pos = pos - ) + ).unwrap() } - PropertyKind::Interval(ivl) => write!(self.sql, "ivl {} {}", op, ivl), - PropertyKind::Reps(reps) => write!(self.sql, "reps {} {}", op, reps), - PropertyKind::Lapses(days) => write!(self.sql, "lapses {} {}", op, days), + PropertyKind::Interval(ivl) => write!(self.sql, "ivl {} {}", op, ivl).unwrap(), + PropertyKind::Reps(reps) => write!(self.sql, "reps {} {}", op, reps).unwrap(), + PropertyKind::Lapses(days) => write!(self.sql, "lapses {} {}", op, days).unwrap(), PropertyKind::Ease(ease) => { - write!(self.sql, "factor {} {}", op, (ease * 1000.0) as u32) - } - PropertyKind::Rated(days, ease) => { - write!(self.sql, "") + write!(self.sql, "factor {} {}", op, (ease * 1000.0) as u32).unwrap() } + PropertyKind::Rated(days, ease) => self.write_rated(*days, *ease, op)? } - .unwrap(); + Ok(()) }