From a2a750f20e1e6660f9f3cb1967fadf697bdf8ec2 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 9 Mar 2023 14:52:04 +0100 Subject: [PATCH] Add Filters to SQL --- schemsearch-cli/src/main.rs | 37 +++++++++++++++++++++++++++++++---- schemsearch-sql/src/filter.rs | 35 +++++++++++++++++++++++++++++++++ schemsearch-sql/src/lib.rs | 6 ++++-- 3 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 schemsearch-sql/src/filter.rs diff --git a/schemsearch-cli/src/main.rs b/schemsearch-cli/src/main.rs index 5c5658f..98f2e2b 100644 --- a/schemsearch-cli/src/main.rs +++ b/schemsearch-cli/src/main.rs @@ -19,7 +19,7 @@ mod types; use std::fs::File; use std::io::{BufWriter, StdoutLock, Write}; -use clap::{command, Arg, ArgAction, Command}; +use clap::{command, Arg, ArgAction, Command, ValueHint}; use schemsearch_files::Schematic; use std::path::Path; use clap::error::ErrorKind; @@ -27,6 +27,7 @@ use schemsearch_lib::{search, SearchBehavior}; use crate::types::{PathSchematicSupplier, SchematicSupplierType}; #[cfg(feature = "sql")] use futures::executor::block_on; +use schemsearch_sql::filter::SchematicFilter; #[cfg(feature = "sql")] use schemsearch_sql::load_all_schematics; #[cfg(feature = "sql")] @@ -39,11 +40,13 @@ fn main() { Arg::new("pattern") .help("The pattern to search for") .required(true) + .value_hint(ValueHint::FilePath) .action(ArgAction::Set), ) .arg( Arg::new("schematic") .help("The schematics to search in") + .value_hint(ValueHint::AnyPath) .action(ArgAction::Append), ) .arg( @@ -95,6 +98,7 @@ fn main() { .help("The output file") .short('O') .long("output-file") + .value_hint(ValueHint::FilePath) .action(ArgAction::Append) ) .arg( @@ -113,10 +117,27 @@ fn main() { let mut cmd = cmd .arg( Arg::new("sql") - .help("The sql file to write to") + .help("Use the SteamWar SQL Database") .short('s') .long("sql") .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("sql-filter-user") + .help("Filter the schematics by the owners userid") + .short('u') + .long("sql-filter-user") + .action(ArgAction::Append) + .value_parser(|s: &str| s.parse::().map_err(|e| e.to_string())) + .requires("sql"), + ) + .arg( + Arg::new("sql-filter-name") + .help("Filter the schematics by the schematic name") + .short('n') + .long("sql-filter-name") + .action(ArgAction::Append) + .requires("sql"), ); let matches = cmd.get_matches_mut(); @@ -148,12 +169,20 @@ fn main() { #[cfg(feature = "sql")] if matches.get_flag("sql") { - for schem in block_on(load_all_schematics()) { + let mut filter = SchematicFilter::default(); + if let Some(x) = matches.get_many::("sql-filter-user") { + filter = filter.user_id(x.collect()); + } + if let Some(x) = matches.get_many::("sql-filter-name") { + filter = filter.name(x.collect()); + } + for schem in block_on(load_all_schematics(filter)) { schematics.push(SchematicSupplierType::SQL(SqlSchematicSupplier{ node: schem })) }; - } else if schematics.is_empty() { + } + if schematics.is_empty() { cmd.error(ErrorKind::MissingRequiredArgument, "No schematics specified").exit(); } diff --git a/schemsearch-sql/src/filter.rs b/schemsearch-sql/src/filter.rs new file mode 100644 index 0000000..7c65e50 --- /dev/null +++ b/schemsearch-sql/src/filter.rs @@ -0,0 +1,35 @@ +#[derive(Default, Debug, Clone)] +pub struct SchematicFilter { + pub user_id: Option>, + pub name: Option>, +} + +impl SchematicFilter { + pub fn new() -> SchematicFilter { + SchematicFilter { + user_id: None, + name: None, + } + } + + pub fn user_id(mut self, user_id: Vec<&u32>) -> SchematicFilter { + self.user_id = Some(user_id.into_iter().map(|id| *id).collect()); + self + } + + pub fn name(mut self, name: Vec<&String>) -> SchematicFilter { + self.name = Some(name.into_iter().map(|name| name.to_string()).collect()); + self + } + + pub fn build(self) -> String { + let mut query = Vec::new(); + if let Some(user_id) = self.user_id { + query.push(user_id.into_iter().map(|id| format!("ND.NodeOwner = {}", id)).collect::>().join(" OR ")); + } + if let Some(name) = self.name { + query.push(name.into_iter().map(|name| format!("SN.NodeName LIKE '%{}%'", name)).collect::>().join(" OR ")); + } + format!("AND ({})", query.join(") AND (")) + } +} \ No newline at end of file diff --git a/schemsearch-sql/src/lib.rs b/schemsearch-sql/src/lib.rs index cb0f2cc..a428e0e 100644 --- a/schemsearch-sql/src/lib.rs +++ b/schemsearch-sql/src/lib.rs @@ -18,8 +18,10 @@ use std::sync::Mutex; use sqlx::{Executor, MySql, MySqlPool, Pool, Row}; use sqlx::mysql::MySqlConnectOptions; +use crate::filter::SchematicFilter; mod properties; +pub mod filter; static mut CONN: Mutex>> = Mutex::new(None); @@ -44,10 +46,10 @@ pub async unsafe fn get_connection() { } } -pub async fn load_all_schematics() -> Vec { +pub async fn load_all_schematics(filter: SchematicFilter) -> Vec { unsafe { get_connection().await; } let mut schematics = Vec::new(); - let rows = unsafe { &CONN }.lock().unwrap().as_mut().unwrap().fetch_all("SELECT SN.NodeId, SN.NodeName FROM NodeData ND INNER JOIN SchematicNode SN ON SN.NodeId = ND.NodeId WHERE NodeFormat = true").await.expect("Failed to fetch schematics"); + let rows = unsafe { &CONN }.lock().unwrap().as_mut().unwrap().fetch_all(format!("SELECT SN.NodeId, SN.NodeName FROM NodeData ND INNER JOIN SchematicNode SN ON SN.NodeId = ND.NodeId WHERE NodeFormat = true {}", filter.build()).as_str()).await.expect("Failed to fetch schematics"); for row in rows { schematics.push(SchematicNode { id: row.get(0),