diff --git a/db/src/lib.rs b/db/src/lib.rs index 07f5bc5b..a67c6562 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -43,7 +43,7 @@ mod entids; pub mod errors; mod metadata; mod schema; -mod types; +pub mod types; mod internal_types; mod upsert_resolution; mod tx; diff --git a/tools/cli/Cargo.toml b/tools/cli/Cargo.toml index 620a8ce4..cd74523b 100644 --- a/tools/cli/Cargo.toml +++ b/tools/cli/Cargo.toml @@ -34,3 +34,12 @@ path = "../../parser-utils" [dependencies.edn] path = "../../edn" + +[dependencies.mentat_query] +path = "../../query" + +[dependencies.mentat_core] +path = "../../core" + +[dependencies.mentat_db] +path = "../../db" diff --git a/tools/cli/src/mentat_cli/input.rs b/tools/cli/src/mentat_cli/input.rs index 6839dc61..2a614e5a 100644 --- a/tools/cli/src/mentat_cli/input.rs +++ b/tools/cli/src/mentat_cli/input.rs @@ -109,6 +109,9 @@ impl InputReader { match cmd { Command::Query(_) | Command::Transact(_) if !cmd.is_complete() => { + // a query or transact is complete if it contains a valid edn. + // if the command is not complete, ask for more from the repl and remember + // which type of command we've found here. self.in_process_cmd = Some(cmd); Ok(More) }, diff --git a/tools/cli/src/mentat_cli/lib.rs b/tools/cli/src/mentat_cli/lib.rs index 8fd95231..b2cf272d 100644 --- a/tools/cli/src/mentat_cli/lib.rs +++ b/tools/cli/src/mentat_cli/lib.rs @@ -22,6 +22,9 @@ extern crate rusqlite; extern crate mentat; extern crate edn; +extern crate mentat_query; +extern crate mentat_core; +extern crate mentat_db; use getopts::Options; diff --git a/tools/cli/src/mentat_cli/repl.rs b/tools/cli/src/mentat_cli/repl.rs index 9507e7ed..a288f20e 100644 --- a/tools/cli/src/mentat_cli/repl.rs +++ b/tools/cli/src/mentat_cli/repl.rs @@ -10,6 +10,9 @@ use std::collections::HashMap; +use mentat::query::QueryResults; +use mentat_core::TypedValue; + use command_parser::{ Command, HELP_COMMAND, @@ -92,6 +95,8 @@ impl Repl { Err(e) => println!("{}", e.to_string()) }; }, + Command::Query(query) => self.query_command(query), + Command::Transact(transaction) => self.transact_command(transaction), _ => unimplemented!(), } } @@ -115,6 +120,66 @@ impl Repl { } } } + + fn query_command(&self, query: String) { + let results = match self.store.query(query){ + Result::Ok(vals) => { + vals + }, + Result::Err(err) => return println!("{:?}.", err), + }; + + if results.is_empty() { + println!("No results found.") + } + + let mut output:String = String::new(); + match results { + QueryResults::Scalar(Some(val)) => { + output.push_str(&self.typed_value_as_string(val) ); + }, + QueryResults::Tuple(Some(vals)) => { + for val in vals { + output.push_str(&format!("{}\t", self.typed_value_as_string(val))); + } + }, + QueryResults::Coll(vv) => { + for val in vv { + output.push_str(&format!("{}\n", self.typed_value_as_string(val))); + } + }, + QueryResults::Rel(vvv) => { + for vv in vvv { + for v in vv { + output.push_str(&format!("{}\t", self.typed_value_as_string(v))); + } + output.push_str("\n"); + } + }, + _ => output.push_str(&format!("No results found.")) + } + println!("\n{}", output); + } + + fn transact_command(&mut self, transaction: String) { + match self.store.transact(transaction) { + Result::Ok(report) => println!("{:?}", report), + Result::Err(err) => println!("{:?}.", err), + } + } + + fn typed_value_as_string(&self, value: TypedValue) -> String { + match value { + TypedValue::Boolean(b) => if b { "true".to_string() } else { "false".to_string() }, + TypedValue::Double(d) => format!("{}", d), + TypedValue::Instant(i) => format!("{}", i), + TypedValue::Keyword(k) => format!("{}", k), + TypedValue::Long(l) => format!("{}", l), + TypedValue::Ref(r) => format!("{}", r), + TypedValue::String(s) => format!("{:?}", s.to_string()), + TypedValue::Uuid(u) => format!("{}", u), + } + } } #[cfg(test)] diff --git a/tools/cli/src/mentat_cli/store.rs b/tools/cli/src/mentat_cli/store.rs index a1689f63..bc49443c 100644 --- a/tools/cli/src/mentat_cli/store.rs +++ b/tools/cli/src/mentat_cli/store.rs @@ -9,13 +9,16 @@ // specific language governing permissions and limitations under the License. use rusqlite; + +use errors as cli; + use mentat::{ new_connection, }; +use mentat::query::QueryResults; use mentat::conn::Conn; - -use errors as cli; +use mentat_db::types::TxReport; pub struct Store { handle: rusqlite::Connection, @@ -48,4 +51,11 @@ impl Store { self.open(None) } + pub fn query(&self, query: String) -> Result { + Ok(try!(self.conn.q_once(&self.handle, &query, None))) + } + + pub fn transact(&mut self, transaction: String) -> Result { + Ok(try!(self.conn.transact(&mut self.handle, &transaction))) + } }