From 0b2a30e71c9430380c554c8ca796c0872c75506e Mon Sep 17 00:00:00 2001 From: Emily Toop Date: Thu, 22 Jun 2017 12:58:21 +0100 Subject: [PATCH] Show schema of current DB --- tools/cli/src/mentat_cli/command_parser.rs | 51 ++++++++++++++++++++-- tools/cli/src/mentat_cli/repl.rs | 10 +++++ tools/cli/src/mentat_cli/store.rs | 11 ++++- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/tools/cli/src/mentat_cli/command_parser.rs b/tools/cli/src/mentat_cli/command_parser.rs index 36d4912f6..5d9f85682 100644 --- a/tools/cli/src/mentat_cli/command_parser.rs +++ b/tools/cli/src/mentat_cli/command_parser.rs @@ -37,6 +37,7 @@ pub static OPEN_COMMAND: &'static str = &"open"; pub static CLOSE_COMMAND: &'static str = &"close"; pub static LONG_QUERY_COMMAND: &'static str = &"query"; pub static SHORT_QUERY_COMMAND: &'static str = &"q"; +pub static SCHEMA_COMMAND: &'static str = &"schema"; pub static LONG_TRANSACT_COMMAND: &'static str = &"transact"; pub static SHORT_TRANSACT_COMMAND: &'static str = &"t"; pub static LONG_EXIT_COMMAND: &'static str = &"exit"; @@ -49,6 +50,7 @@ pub enum Command { Help(Vec), Open(String), Query(String), + Schema, Transact(String), } @@ -66,7 +68,8 @@ impl Command { &Command::Help(_) | &Command::Open(_) | &Command::Close | - &Command::Exit => true + &Command::Exit | + &Command::Schema => true } } @@ -83,13 +86,16 @@ impl Command { }, &Command::Open(ref args) => { format!(".{} {}", OPEN_COMMAND, args) - } + }, &Command::Close => { format!(".{}", CLOSE_COMMAND) }, &Command::Exit => { format!(".{}", LONG_EXIT_COMMAND) }, + &Command::Schema => { + format!(".{}", SCHEMA_COMMAND) + }, } } } @@ -129,6 +135,15 @@ pub fn command(s: &str) -> Result { } Ok(Command::Close) }); + + let schema_parser = string(SCHEMA_COMMAND) + .with(no_arg_parser()) + .map(|args| { + if !args.is_empty() { + bail!(cli::ErrorKind::CommandParse(format!("Unrecognized argument {:?}", args[0])) ); + } + Ok(Command::Schema) + }); let exit_parser = try(string(LONG_EXIT_COMMAND)).or(try(string(SHORT_EXIT_COMMAND))) .with(no_arg_parser()) @@ -161,12 +176,13 @@ pub fn command(s: &str) -> Result { spaces() .skip(token('.')) - .with(choice::<[&mut Parser>; 6], _> + .with(choice::<[&mut Parser>; 7], _> ([&mut try(help_parser), &mut try(open_parser), &mut try(close_parser), &mut try(exit_parser), &mut try(query_parser), + &mut try(schema_parser), &mut try(transact_parser)])) .parse(s) .unwrap_or((Err(cli::ErrorKind::CommandParse(format!("Invalid command {:?}", s)).into()), "")).0 @@ -323,7 +339,7 @@ mod tests { let cmd = command(&input).expect("Expected exit command"); match cmd { Command::Exit => assert!(true), - _ => assert!(false) + _ => assert!(false) } } @@ -346,6 +362,33 @@ mod tests { _ => assert!(false) } } + + #[test] + fn test_schema_parser_with_args() { + let input = ".schema arg1"; + let err = command(&input).expect_err("Expected an error"); + assert_eq!(err.to_string(), format!("Invalid command {:?}", input)); + } + + #[test] + fn test_schema_parser_no_args() { + let input = ".schema"; + let cmd = command(&input).expect("Expected schema command"); + match cmd { + Command::Schema => assert!(true), + _ => assert!(false) + } + } + + #[test] + fn test_schema_parser_no_args_trailing_whitespace() { + let input = ".schema "; + let cmd = command(&input).expect("Expected schema command"); + match cmd { + Command::Schema => assert!(true), + _ => assert!(false) + } + } #[test] fn test_query_parser_complete_edn() { diff --git a/tools/cli/src/mentat_cli/repl.rs b/tools/cli/src/mentat_cli/repl.rs index 5c3cb790e..acf1d208f 100644 --- a/tools/cli/src/mentat_cli/repl.rs +++ b/tools/cli/src/mentat_cli/repl.rs @@ -22,6 +22,7 @@ use command_parser::{ OPEN_COMMAND, LONG_QUERY_COMMAND, SHORT_QUERY_COMMAND, + SCHEMA_COMMAND, LONG_TRANSACT_COMMAND, SHORT_TRANSACT_COMMAND, LONG_EXIT_COMMAND, @@ -48,6 +49,7 @@ lazy_static! { map.insert(OPEN_COMMAND, "Open a database at path."); map.insert(LONG_QUERY_COMMAND, "Execute a query against the current open database."); map.insert(SHORT_QUERY_COMMAND, "Shortcut for `.query`. Execute a query against the current open database."); + map.insert(SCHEMA_COMMAND, "Output the schema for the current open database."); map.insert(LONG_TRANSACT_COMMAND, "Execute a transact against the current open database."); map.insert(SHORT_TRANSACT_COMMAND, "Shortcut for `.transact`. Execute a transact against the current open database."); map @@ -112,6 +114,14 @@ impl Repl { }, Command::Close => self.close(), Command::Query(query) => self.execute_query(query), + Command::Schema => { + let edn = self.store.fetch_schema(); + match edn.to_pretty(120) { + Ok(s) => println!("{}", s), + Err(e) => println!("{}", e) + }; + + } Command::Transact(transaction) => self.execute_transact(transaction), Command::Exit => { self.close(); diff --git a/tools/cli/src/mentat_cli/store.rs b/tools/cli/src/mentat_cli/store.rs index bc49443c6..9bfc1e8de 100644 --- a/tools/cli/src/mentat_cli/store.rs +++ b/tools/cli/src/mentat_cli/store.rs @@ -10,11 +10,14 @@ use rusqlite; +use edn; + use errors as cli; use mentat::{ new_connection, }; + use mentat::query::QueryResults; use mentat::conn::Conn; @@ -52,10 +55,14 @@ impl Store { } pub fn query(&self, query: String) -> Result { - Ok(try!(self.conn.q_once(&self.handle, &query, None))) + Ok(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))) + Ok(self.conn.transact(&mut self.handle, &transaction)?) + } + + pub fn fetch_schema(&self) -> edn::Value { + self.conn.current_schema().to_edn_value() } }