From fdc45cea3fac75d3926d1c563468d0a56472cfdd Mon Sep 17 00:00:00 2001 From: Abraham Toriz Date: Wed, 30 Jun 2021 19:20:10 -0500 Subject: [PATCH] allow to filter by start and end --- src/commands/display.rs | 77 +++++++++++++++++++++++++++++------- src/database.rs | 88 ++++++++++++++++++++++++++++++++++++++--- src/main.rs | 2 +- 3 files changed, 145 insertions(+), 22 deletions(-) diff --git a/src/commands/display.rs b/src/commands/display.rs index d95814f..93d13c2 100644 --- a/src/commands/display.rs +++ b/src/commands/display.rs @@ -97,36 +97,30 @@ pub struct DisplayCommand { } impl<'a> Command<'a> for DisplayCommand { type Args = Args; - fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, config: &Config) -> error::Result<()> + fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config) -> error::Result<()> where D: Database, O: Write, E: Write, { let entries = match args.sheet { - Some(Sheet::All) => db.entries_all_visible()?, - Some(Sheet::Full) => db.entries_full()?, - Some(Sheet::Sheet(name)) => db.entries_by_sheet(&name)?, + Some(Sheet::All) => db.entries_all_visible(args.start, args.end)?, + Some(Sheet::Full) => db.entries_full(args.start, args.end)?, + Some(Sheet::Sheet(name)) => db.entries_by_sheet(&name, args.start, args.end)?, None => { let current_sheet = db.current_sheet()?.unwrap_or("default".into()); - db.entries_by_sheet(¤t_sheet)? + db.entries_by_sheet(¤t_sheet, args.start, args.end)? } }; - let entries = if let DBVersion::Timetrap = db.version()? { + let (entries, needs_warning) = if let DBVersion::Timetrap = db.version()? { // this indicates that times in the database are specified in the // local time and need to be converted to utc before displaying - writeln!( - err, - "{} You are using the old timetrap format, it is advised that \ - you update your database using t migrate", - Yellow.bold().paint("[WARNING]"), - )?; - local_to_utc_vec(entries)? + (local_to_utc_vec(entries)?, true) } else { - entries + (entries, false) }; args.format.print_formatted( @@ -135,7 +129,18 @@ impl<'a> Command<'a> for DisplayCommand { Utc::now(), args.ids, term_width(), - ) + )?; + + if needs_warning { + writeln!( + err, + "{} You are using the old timetrap format, it is advised that \ + you update your database using t migrate", + Yellow.bold().paint("[WARNING]"), + )?; + } + + Ok(()) } } @@ -153,6 +158,7 @@ mod tests { let mut out = Vec::new(); let mut err = Vec::new(); let config = Default::default(); + std::env::set_var("TZ", "UTC"); DisplayCommand::handle(args, &mut db, &mut out, &mut err, &config).unwrap(); @@ -176,4 +182,45 @@ mod tests { assert!(false, "start with a newly created database"); assert!(false, "correctly display times in local timezone"); } + + #[test] + fn filter_by_start() { + let args = Args { + format: Formatter::Csv, + start: Some(Utc.ymd(2021, 6, 30).and_hms(10, 5, 0)), + ..Default::default() + }; + let mut db = SqliteDatabase::from_memory().unwrap(); + let mut out = Vec::new(); + let mut err = Vec::new(); + let config = Default::default(); + + db.init().unwrap(); + + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default".into()).unwrap(); + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default".into()).unwrap(); + + DisplayCommand::handle(args, &mut db, &mut out, &mut err, &config).unwrap(); + + assert_eq!(PrettyString(&String::from_utf8_lossy(&out)), PrettyString("start,end,note,sheet +2021-06-30T10:10:00Z,,hola,default +")); + + assert_eq!( + String::from_utf8_lossy(&err), + String::new(), + ); + } + + #[test] + fn filter_by_end() { + } + + #[test] + fn filter_by_start_and_end() { + } + + #[test] + fn filter_by_match() { + } } diff --git a/src/database.rs b/src/database.rs index beac308..b51b05e 100644 --- a/src/database.rs +++ b/src/database.rs @@ -39,6 +39,7 @@ pub trait Database { `value` varchar(255) ) ", &[])?; + self.execute("INSERT INTO meta (key, value) VALUES ('database_version', 1)", &[])?; Ok(()) } @@ -46,16 +47,91 @@ pub trait Database { // ------------- // Entry queries // ------------- - fn entries_by_sheet(&self, sheet: &str) -> Result> { - self.entry_query("select * from entries where sheet=?1 order by start asc", &[&sheet]) + fn entries_by_sheet(&self, sheet: &str, start: Option>, end: Option>) -> Result> { + match (start, end) { + (Some(start), Some(end)) => { + self.entry_query( + "select * from entries where sheet=?1 and start >= ?2 and end <= ?2 order by start asc", + &[&sheet, &start, &end] + ) + } + (Some(start), None) => { + self.entry_query( + "select * from entries where sheet=?1 and start >= ?2 order by start asc", + &[&sheet, &start] + ) + } + (None, Some(end)) => { + self.entry_query( + "select * from entries where sheet=?1 and end <= ?2 order by start asc", + &[&sheet, &end] + ) + } + (None, None) => { + self.entry_query( + "select * from entries where sheet=?1 order by start asc", + &[&sheet] + ) + } + } } - fn entries_all_visible(&self) -> Result> { - self.entry_query("select * from entries where sheet not like '!_%' escape \"!\" order by sheet asc, start asc", &[]) + fn entries_all_visible(&self, start: Option>, end: Option>) -> Result> { + match (start, end) { + (Some(start), Some(end)) => { + self.entry_query( + "select * from entries where sheet not like '!_%' escape \"!\" and start >= ?2 and end <= ?2 order by start asc", + &[&start, &end] + ) + } + (Some(start), None) => { + self.entry_query( + "select * from entries where sheet not like '!_%' escape \"!\" and start >= ?2 order by start asc", + &[&start] + ) + } + (None, Some(end)) => { + self.entry_query( + "select * from entries where sheet not like '!_%' escape \"!\" and end <= ?2 order by start asc", + &[&end] + ) + } + (None, None) => { + self.entry_query( + "select * from entries where sheet not like '!_%' escape \"!\" order by start asc", + &[] + ) + } + } } - fn entries_full(&self) -> Result> { - self.entry_query("select * from entries order by sheet asc, start asc", &[]) + fn entries_full(&self, start: Option>, end: Option>) -> Result> { + match (start, end) { + (Some(start), Some(end)) => { + self.entry_query( + "select * from entries where start >= ?2 and end <= ?2 order by start asc", + &[&start, &end] + ) + } + (Some(start), None) => { + self.entry_query( + "select * from entries where start >= ?2 order by start asc", + &[&start] + ) + } + (None, Some(end)) => { + self.entry_query( + "select * from entries where end <= ?2 order by start asc", + &[&end] + ) + } + (None, None) => { + self.entry_query( + "select * from entries where sheet=?1 order by start asc", + &[] + ) + } + } } fn entry_insert(&mut self, start: DateTime, end: Option>, note: Option, sheet: String) -> Result<()> { diff --git a/src/main.rs b/src/main.rs index 7b6d286..4085719 100644 --- a/src/main.rs +++ b/src/main.rs @@ -123,7 +123,7 @@ fn main() { .arg(Arg::with_name("format") .short("f").long("format") .takes_value(true).value_name("FORMAT").default_value("text") - .help("The output format. Valid built-in formats are ical, csv, json, ids, factor, and text (default). Documentation on defining custom formats can be found in the README included in this distribution.")) + .help("The output format. Valid built-in formats are ical, csv, json, ids, factor, and text. Documentation on defining custom formats can be found in the README included in this distribution.")) .arg(Arg::with_name("grep") .short("g").long("grep") .takes_value(true).value_name("REGEXP")