summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjean-santos <ewqjean@gmail.com>2023-03-27 18:33:04 -0300
committerGitHub <noreply@github.com>2023-03-27 22:33:04 +0100
commitcaf2ddfb9ff7a5f78cd10da0dc030fdeee7c0fe0 (patch)
tree1c5107792f763e52eec42be0fc1605f9570ed169
parentc64674dc23abb2899f0ca6fcd5f3cb31b0b9b853 (diff)
client filtering done in query (#629)
-rw-r--r--atuin-client/src/database.rs71
-rw-r--r--src/command/client/search.rs107
-rw-r--r--src/command/client/search/engines/db.rs11
-rw-r--r--src/command/client/search/interactive.rs3
4 files changed, 84 insertions, 108 deletions
diff --git a/atuin-client/src/database.rs b/atuin-client/src/database.rs
index fa39f71b6..1a577a706 100644
--- a/atuin-client/src/database.rs
+++ b/atuin-client/src/database.rs
@@ -25,6 +25,17 @@ pub struct Context {
pub hostname: String,
}
+#[derive(Default, Clone)]
+pub struct OptFilters {
+ pub exit: Option<i64>,
+ pub exclude_exit: Option<i64>,
+ pub cwd: Option<String>,
+ pub exclude_cwd: Option<String>,
+ pub before: Option<String>,
+ pub after: Option<String>,
+ pub limit: Option<i64>,
+}
+
pub fn current_context() -> Context {
let Ok(session) = env::var("ATUIN_SESSION") else {
eprintln!("ERROR: Failed to find $ATUIN_SESSION in the environment. Check that you have correctly set up your shell.");
@@ -79,9 +90,7 @@ pub trait Database: Send + Sync + 'static {
filter: FilterMode,
context: &Context,
query: &str,
- limit: Option<i64>,
- before: Option<i64>,
- after: Option<i64>,
+ filter_options: OptFilters,
) -> Result<Vec<History>>;
async fn query_history(&self, query: &str) -> Result<Vec<History>>;
@@ -340,9 +349,7 @@ impl Database for Sqlite {
filter: FilterMode,
context: &Context,
query: &str,
- limit: Option<i64>,
- before: Option<i64>,
- after: Option<i64>,
+ filter_options: OptFilters,
) -> Result<Vec<History>> {
let mut sql = SqlBuilder::select_from("history");
@@ -350,18 +357,10 @@ impl Database for Sqlite {
.having("max(timestamp)")
.order_desc("timestamp");
- if let Some(limit) = limit {
+ if let Some(limit) = filter_options.limit {
sql.limit(limit);
}
- if let Some(after) = after {
- sql.and_where_gt("timestamp", after);
- }
-
- if let Some(before) = before {
- sql.and_where_lt("timestamp", before);
- }
-
match filter {
FilterMode::Global => &mut sql,
FilterMode::Host => sql.and_where_eq("hostname", quote(&context.hostname)),
@@ -421,6 +420,32 @@ impl Database for Sqlite {
}
};
+ filter_options
+ .exit
+ .map(|exit| sql.and_where_eq("exit", exit));
+
+ filter_options
+ .exclude_exit
+ .map(|exclude_exit| sql.and_where_ne("exit", exclude_exit));
+
+ filter_options
+ .cwd
+ .map(|cwd| sql.and_where_eq("cwd", quote(cwd)));
+
+ filter_options
+ .exclude_cwd
+ .map(|exclude_cwd| sql.and_where_ne("cwd", quote(exclude_cwd)));
+
+ filter_options.before.map(|before| {
+ interim::parse_date_string(before.as_str(), Utc::now(), interim::Dialect::Uk)
+ .map(|before| sql.and_where_lt("timestamp", quote(before.timestamp_nanos())))
+ });
+
+ filter_options.after.map(|after| {
+ interim::parse_date_string(after.as_str(), Utc::now(), interim::Dialect::Uk)
+ .map(|after| sql.and_where_gt("timestamp", quote(after.timestamp_nanos())))
+ });
+
let query = sql.sql().expect("bug in search query. please report");
let res = sqlx::query(&query)
@@ -508,7 +533,15 @@ mod test {
};
let results = db
- .search(mode, filter_mode, &context, query, None, None, None)
+ .search(
+ mode,
+ filter_mode,
+ &context,
+ query,
+ OptFilters {
+ ..Default::default()
+ },
+ )
.await?;
assert_eq!(
@@ -718,9 +751,9 @@ mod test {
FilterMode::Global,
&context,
"",
- None,
- None,
- None,
+ OptFilters {
+ ..Default::default()
+ },
)
.await
.unwrap();
diff --git a/src/command/client/search.rs b/src/command/client/search.rs
index c407eb083..fb3a1a393 100644
--- a/src/command/client/search.rs
+++ b/src/command/client/search.rs
@@ -1,11 +1,10 @@
use atuin_common::utils;
-use chrono::Utc;
use clap::Parser;
use eyre::Result;
use atuin_client::{
- database::current_context,
database::Database,
+ database::{current_context, OptFilters},
history::History,
settings::{FilterMode, SearchMode, Settings},
};
@@ -103,19 +102,18 @@ impl Cmd {
} else {
let list_mode = ListMode::from_flags(self.human, self.cmd_only);
- let mut entries = run_non_interactive(
- settings,
- self.cwd.clone(),
- self.exit,
- self.exclude_exit,
- self.exclude_cwd.clone(),
- self.before.clone(),
- self.after.clone(),
- self.limit,
- &self.query,
- &mut db,
- )
- .await?;
+ let opt_filter = OptFilters {
+ exit: self.exit,
+ exclude_exit: self.exclude_exit,
+ cwd: self.cwd,
+ exclude_cwd: self.exclude_cwd,
+ before: self.before,
+ after: self.after,
+ limit: self.limit,
+ };
+
+ let mut entries =
+ run_non_interactive(settings, opt_filter.clone(), &self.query, &mut db).await?;
if entries.is_empty() {
std::process::exit(1)
@@ -132,19 +130,9 @@ impl Cmd {
db.delete(entry.clone()).await?;
}
- entries = run_non_interactive(
- settings,
- self.cwd.clone(),
- self.exit,
- self.exclude_exit,
- self.exclude_cwd.clone(),
- self.before.clone(),
- self.after.clone(),
- self.limit,
- &self.query,
- &mut db,
- )
- .await?;
+ entries =
+ run_non_interactive(settings, opt_filter.clone(), &self.query, &mut db)
+ .await?;
}
} else {
super::history::print_list(&entries, list_mode, self.format.as_deref());
@@ -159,33 +147,22 @@ impl Cmd {
#[allow(clippy::too_many_arguments)]
async fn run_non_interactive(
settings: &Settings,
- cwd: Option<String>,
- exit: Option<i64>,
- exclude_exit: Option<i64>,
- exclude_cwd: Option<String>,
- before: Option<String>,
- after: Option<String>,
- limit: Option<i64>,
+ filter_options: OptFilters,
query: &[String],
db: &mut impl Database,
) -> Result<Vec<History>> {
- let dir = if cwd.as_deref() == Some(".") {
+ let dir = if filter_options.cwd.as_deref() == Some(".") {
Some(utils::get_current_dir())
} else {
- cwd
+ filter_options.cwd
};
let context = current_context();
- let before = before.and_then(|b| {
- interim::parse_date_string(b.as_str(), Utc::now(), interim::Dialect::Uk)
- .map_or(None, |d| Some(d.timestamp_nanos()))
- });
-
- let after = after.and_then(|a| {
- interim::parse_date_string(a.as_str(), Utc::now(), interim::Dialect::Uk)
- .map_or(None, |d| Some(d.timestamp_nanos()))
- });
+ let opt_filter = OptFilters {
+ cwd: dir,
+ ..filter_options
+ };
let results = db
.search(
@@ -193,45 +170,9 @@ async fn run_non_interactive(
settings.filter_mode,
&context,
query.join(" ").as_str(),
- limit,
- before,
- after,
+ opt_filter,
)
.await?;
- // TODO: This filtering would be better done in the SQL query, I just
- // need a nice way of building queries.
- let results: Vec<History> = results
- .iter()
- .filter(|h| {
- if let Some(exit) = exit {
- if h.exit != exit {
- return false;
- }
- }
-
- if let Some(exit) = exclude_exit {
- if h.exit == exit {
- return false;
- }
- }
-
- if let Some(cwd) = &exclude_cwd {
- if h.cwd.as_str() == cwd.as_str() {
- return false;
- }
- }
-
- if let Some(cwd) = &dir {
- if h.cwd.as_str() != cwd.as_str() {
- return false;
- }
- }
-
- true
- })
- .map(std::borrow::ToOwned::to_owned)
- .collect();
-
Ok(results)
}
diff --git a/src/command/client/search/engines/db.rs b/src/command/client/search/engines/db.rs
index 5a35da100..b4f24561d 100644
--- a/src/command/client/search/engines/db.rs
+++ b/src/command/client/search/engines/db.rs
@@ -1,5 +1,7 @@
use async_trait::async_trait;
-use atuin_client::{database::Database, history::History, settings::SearchMode};
+use atuin_client::{
+ database::Database, database::OptFilters, history::History, settings::SearchMode,
+};
use eyre::Result;
use super::{SearchEngine, SearchState};
@@ -19,9 +21,10 @@ impl SearchEngine for Search {
state.filter_mode,
&state.context,
state.input.as_str(),
- Some(200),
- None,
- None,
+ OptFilters {
+ limit: Some(200),
+ ..Default::default()
+ },
)
.await?
.into_iter()
diff --git a/src/command/client/search/interactive.rs b/src/command/client/search/interactive.rs
index a7ee9baec..5038fc832 100644
--- a/src/command/client/search/interactive.rs
+++ b/src/command/client/search/interactive.rs
@@ -13,8 +13,7 @@ use semver::Version;
use unicode_width::UnicodeWidthStr;
use atuin_client::{
- database::current_context,
- database::Database,
+ database::{current_context, Database},
history::History,
settings::{ExitMode, FilterMode, SearchMode, Settings},
};