show attributes of current database

This commit is contained in:
Emily Toop 2017-06-28 16:58:29 -07:00
parent a9c05ba9b7
commit 9932a98c6f
3 changed files with 72 additions and 4 deletions

View file

@ -38,6 +38,7 @@ 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 ATTRIBUTES_COMMAND: &'static str = &"attributes";
pub static LONG_TRANSACT_COMMAND: &'static str = &"transact";
pub static SHORT_TRANSACT_COMMAND: &'static str = &"t";
pub static LONG_EXIT_COMMAND: &'static str = &"exit";
@ -51,6 +52,7 @@ pub enum Command {
Open(String),
Query(String),
Schema,
Attributes,
Transact(String),
}
@ -69,7 +71,8 @@ impl Command {
&Command::Open(_) |
&Command::Close |
&Command::Exit |
&Command::Schema => true
&Command::Schema |
&Command::Attributes => true
}
}
@ -96,6 +99,9 @@ impl Command {
&Command::Schema => {
format!(".{}", SCHEMA_COMMAND)
},
&Command::Attributes => {
format!(".{}", ATTRIBUTES_COMMAND)
},
}
}
}
@ -144,6 +150,15 @@ pub fn command(s: &str) -> Result<Command, cli::Error> {
}
Ok(Command::Schema)
});
let attributes_parser = string(ATTRIBUTES_COMMAND)
.with(no_arg_parser())
.map(|args| {
if !args.is_empty() {
bail!(cli::ErrorKind::CommandParse(format!("Unrecognized argument {:?}", args[0])) );
}
Ok(Command::Attributes)
});
let exit_parser = try(string(LONG_EXIT_COMMAND)).or(try(string(SHORT_EXIT_COMMAND)))
.with(no_arg_parser())
@ -176,13 +191,14 @@ pub fn command(s: &str) -> Result<Command, cli::Error> {
spaces()
.skip(token('.'))
.with(choice::<[&mut Parser<Input = _, Output = Result<Command, cli::Error>>; 7], _>
.with(choice::<[&mut Parser<Input = _, Output = Result<Command, cli::Error>>; 8], _>
([&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(attributes_parser),
&mut try(transact_parser)]))
.parse(s)
.unwrap_or((Err(cli::ErrorKind::CommandParse(format!("Invalid command {:?}", s)).into()), "")).0
@ -390,6 +406,33 @@ mod tests {
}
}
#[test]
fn test_attributes_parser_with_args() {
let input = ".attributes arg1";
let err = command(&input).expect_err("Expected an error");
assert_eq!(err.to_string(), format!("Invalid command {:?}", input));
}
#[test]
fn test_attributes_parser_no_args() {
let input = ".attributes";
let cmd = command(&input).expect("Expected attributes command");
match cmd {
Command::Attributes => assert!(true),
_ => assert!(false)
}
}
#[test]
fn test_attributes_parser_no_args_trailing_whitespace() {
let input = ".attributes ";
let cmd = command(&input).expect("Expected attributes command");
match cmd {
Command::Attributes => assert!(true),
_ => assert!(false)
}
}
#[test]
fn test_query_parser_complete_edn() {
let input = ".q [:find ?x :where [?x foo/bar ?y]]";

View file

@ -27,6 +27,7 @@ use command_parser::{
SHORT_TRANSACT_COMMAND,
LONG_EXIT_COMMAND,
SHORT_EXIT_COMMAND,
ATTRIBUTES_COMMAND,
};
use input::InputReader;
use input::InputResult::{
@ -43,6 +44,7 @@ use store::{
lazy_static! {
static ref COMMAND_HELP: HashMap<&'static str, &'static str> = {
let mut map = HashMap::new();
map.insert(ATTRIBUTES_COMMAND, "Output the attributes for the schema in the current open database.");
map.insert(LONG_EXIT_COMMAND, "Close the current database and exit the REPL.");
map.insert(SHORT_EXIT_COMMAND, "Shortcut for `.exit`. Close the current database and exit the REPL.");
map.insert(HELP_COMMAND, "Show help for commands.");
@ -120,8 +122,14 @@ impl Repl {
Ok(s) => println!("{}", s),
Err(e) => println!("{}", e)
};
}
},
Command::Attributes => {
let edn = self.store.fetch_attributes();
match edn.to_pretty(120) {
Ok(s) => println!("{}", s),
Err(e) => println!("{}", e)
};
},
Command::Transact(transaction) => self.execute_transact(transaction),
Command::Exit => {
self.close();

View file

@ -62,7 +62,24 @@ impl Store {
Ok(self.conn.transact(&mut self.handle, &transaction)?)
}
// the schema is the entire schema of the store including structure used to describe the store.
pub fn fetch_schema(&self) -> edn::Value {
self.conn.current_schema().to_edn_value()
}
// the attributes are the specific attributes added to the schema for this particular store.
pub fn fetch_attributes(&self) -> edn::Value {
let schema = self.conn.current_schema();
edn::Value::Vector((&schema.schema_map).iter()
.filter_map(|(entid, attribute)| {
if let Some(ident) = schema.get_ident(*entid) {
if !ident.namespace.starts_with("db") {
return Some(attribute.to_edn_value(Some(ident.clone())));
}
}
return None;
})
.collect())
}
}