Pre: Remove open_empty
.
This was a work-around for Tolstoy, which couldn't gracefully handle syncing a store with a bootstrap transaction. Tolstoy now handles that single transaction, so this is no longer necessary.
This commit is contained in:
parent
8ddbd18f5f
commit
0b84a0802d
3 changed files with 9 additions and 123 deletions
41
src/store.rs
41
src/store.rs
|
@ -89,22 +89,6 @@ impl Store {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a totally blank store with no bootstrap schema. Use `open` instead.
|
|
||||||
pub fn open_empty(path: &str) -> Result<Store> {
|
|
||||||
if !path.is_empty() {
|
|
||||||
if Path::new(path).exists() {
|
|
||||||
bail!(MentatError::PathAlreadyExists(path.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut connection = ::new_connection(path)?;
|
|
||||||
let conn = Conn::empty(&mut connection)?;
|
|
||||||
Ok(Store {
|
|
||||||
conn: conn,
|
|
||||||
sqlite: connection,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transact(&mut self, transaction: &str) -> Result<TxReport> {
|
pub fn transact(&mut self, transaction: &str) -> Result<TxReport> {
|
||||||
let mut ip = self.begin_transaction()?;
|
let mut ip = self.begin_transaction()?;
|
||||||
let report = ip.transact(transaction)?;
|
let report = ip.transact(transaction)?;
|
||||||
|
@ -127,28 +111,9 @@ impl Store {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Variant of `open_empty` that allows a key (for encryption/decryption) to
|
/// Change the key for a database that was opened using `open_with_key` (using `PRAGMA
|
||||||
/// be supplied. Fails unless linked against sqlcipher (or something else
|
/// rekey`). Fails unless linked against sqlcipher (or something else that supports the Sqlite
|
||||||
/// that supports the Sqlite Encryption Extension).
|
/// Encryption Extension).
|
||||||
pub fn open_empty_with_key(path: &str, encryption_key: &str) -> Result<Store> {
|
|
||||||
if !path.is_empty() {
|
|
||||||
if Path::new(path).exists() {
|
|
||||||
bail!(MentatError::PathAlreadyExists(path.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut connection = ::new_connection_with_key(path, encryption_key)?;
|
|
||||||
let conn = Conn::empty(&mut connection)?;
|
|
||||||
Ok(Store {
|
|
||||||
conn: conn,
|
|
||||||
sqlite: connection,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change the key for a database that was opened using `open_with_key` or
|
|
||||||
/// `open_empty_with_key` (using `PRAGMA rekey`). Fails unless linked
|
|
||||||
/// against sqlcipher (or something else that supports the Sqlite Encryption
|
|
||||||
/// Extension).
|
|
||||||
pub fn change_encryption_key(&mut self, new_encryption_key: &str) -> Result<()> {
|
pub fn change_encryption_key(&mut self, new_encryption_key: &str) -> Result<()> {
|
||||||
::change_encryption_key(&self.sqlite, new_encryption_key)?;
|
::change_encryption_key(&self.sqlite, new_encryption_key)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -51,9 +51,7 @@ pub static COMMAND_HELP: &'static str = &"help";
|
||||||
pub static COMMAND_IMPORT_LONG: &'static str = &"import";
|
pub static COMMAND_IMPORT_LONG: &'static str = &"import";
|
||||||
pub static COMMAND_IMPORT_SHORT: &'static str = &"i";
|
pub static COMMAND_IMPORT_SHORT: &'static str = &"i";
|
||||||
pub static COMMAND_OPEN: &'static str = &"open";
|
pub static COMMAND_OPEN: &'static str = &"open";
|
||||||
pub static COMMAND_OPEN_EMPTY: &'static str = &"empty";
|
|
||||||
pub static COMMAND_OPEN_ENCRYPTED: &'static str = &"open_encrypted";
|
pub static COMMAND_OPEN_ENCRYPTED: &'static str = &"open_encrypted";
|
||||||
pub static COMMAND_OPEN_EMPTY_ENCRYPTED: &'static str = &"empty_encrypted";
|
|
||||||
pub static COMMAND_QUERY_LONG: &'static str = &"query";
|
pub static COMMAND_QUERY_LONG: &'static str = &"query";
|
||||||
pub static COMMAND_QUERY_SHORT: &'static str = &"q";
|
pub static COMMAND_QUERY_SHORT: &'static str = &"q";
|
||||||
pub static COMMAND_QUERY_EXPLAIN_LONG: &'static str = &"explain_query";
|
pub static COMMAND_QUERY_EXPLAIN_LONG: &'static str = &"explain_query";
|
||||||
|
@ -73,9 +71,7 @@ pub enum Command {
|
||||||
Help(Vec<String>),
|
Help(Vec<String>),
|
||||||
Import(String),
|
Import(String),
|
||||||
Open(String),
|
Open(String),
|
||||||
OpenEmpty(String),
|
|
||||||
OpenEncrypted(String, String),
|
OpenEncrypted(String, String),
|
||||||
OpenEmptyEncrypted(String, String),
|
|
||||||
Query(String),
|
Query(String),
|
||||||
QueryExplain(String),
|
QueryExplain(String),
|
||||||
QueryPrepared(String),
|
QueryPrepared(String),
|
||||||
|
@ -105,9 +101,7 @@ impl Command {
|
||||||
&Command::Help(_) |
|
&Command::Help(_) |
|
||||||
&Command::Import(_) |
|
&Command::Import(_) |
|
||||||
&Command::Open(_) |
|
&Command::Open(_) |
|
||||||
&Command::OpenEmpty(_) |
|
|
||||||
&Command::OpenEncrypted(_, _) |
|
&Command::OpenEncrypted(_, _) |
|
||||||
&Command::OpenEmptyEncrypted(_, _) |
|
|
||||||
&Command::Timer(_) |
|
&Command::Timer(_) |
|
||||||
&Command::Schema |
|
&Command::Schema |
|
||||||
&Command::Sync(_)
|
&Command::Sync(_)
|
||||||
|
@ -128,9 +122,7 @@ impl Command {
|
||||||
&Command::Exit |
|
&Command::Exit |
|
||||||
&Command::Help(_) |
|
&Command::Help(_) |
|
||||||
&Command::Open(_) |
|
&Command::Open(_) |
|
||||||
&Command::OpenEmpty(_) |
|
|
||||||
&Command::OpenEncrypted(_, _) |
|
&Command::OpenEncrypted(_, _) |
|
||||||
&Command::OpenEmptyEncrypted(_, _) |
|
|
||||||
&Command::QueryExplain(_) |
|
&Command::QueryExplain(_) |
|
||||||
&Command::Timer(_) |
|
&Command::Timer(_) |
|
||||||
&Command::Schema |
|
&Command::Schema |
|
||||||
|
@ -159,15 +151,9 @@ impl Command {
|
||||||
&Command::Open(ref args) => {
|
&Command::Open(ref args) => {
|
||||||
format!(".{} {}", COMMAND_OPEN, args)
|
format!(".{} {}", COMMAND_OPEN, args)
|
||||||
},
|
},
|
||||||
&Command::OpenEmpty(ref args) => {
|
|
||||||
format!(".{} {}", COMMAND_OPEN_EMPTY, args)
|
|
||||||
},
|
|
||||||
&Command::OpenEncrypted(ref db, ref key) => {
|
&Command::OpenEncrypted(ref db, ref key) => {
|
||||||
format!(".{} {} {}", COMMAND_OPEN_ENCRYPTED, db, key)
|
format!(".{} {} {}", COMMAND_OPEN_ENCRYPTED, db, key)
|
||||||
},
|
},
|
||||||
&Command::OpenEmptyEncrypted(ref db, ref key) => {
|
|
||||||
format!(".{} {} {}", COMMAND_OPEN_EMPTY_ENCRYPTED, db, key)
|
|
||||||
},
|
|
||||||
&Command::Query(ref args) => {
|
&Command::Query(ref args) => {
|
||||||
format!(".{} {}", COMMAND_QUERY_LONG, args)
|
format!(".{} {}", COMMAND_QUERY_LONG, args)
|
||||||
},
|
},
|
||||||
|
@ -282,15 +268,9 @@ pub fn command(s: &str) -> Result<Command, Error> {
|
||||||
let open_parser = opener(COMMAND_OPEN, 1).map(|args_res|
|
let open_parser = opener(COMMAND_OPEN, 1).map(|args_res|
|
||||||
args_res.map(|args| Command::Open(args[0].clone())));
|
args_res.map(|args| Command::Open(args[0].clone())));
|
||||||
|
|
||||||
let open_empty_parser = opener(COMMAND_OPEN_EMPTY, 1).map(|args_res|
|
|
||||||
args_res.map(|args| Command::OpenEmpty(args[0].clone())));
|
|
||||||
|
|
||||||
let open_encrypted_parser = opener(COMMAND_OPEN_ENCRYPTED, 2).map(|args_res|
|
let open_encrypted_parser = opener(COMMAND_OPEN_ENCRYPTED, 2).map(|args_res|
|
||||||
args_res.map(|args| Command::OpenEncrypted(args[0].clone(), args[1].clone())));
|
args_res.map(|args| Command::OpenEncrypted(args[0].clone(), args[1].clone())));
|
||||||
|
|
||||||
let open_empty_encrypted_parser = opener(COMMAND_OPEN_EMPTY_ENCRYPTED, 2).map(|args_res|
|
|
||||||
args_res.map(|args| Command::OpenEmptyEncrypted(args[0].clone(), args[1].clone())));
|
|
||||||
|
|
||||||
let query_parser = try(string(COMMAND_QUERY_LONG)).or(try(string(COMMAND_QUERY_SHORT)))
|
let query_parser = try(string(COMMAND_QUERY_LONG)).or(try(string(COMMAND_QUERY_SHORT)))
|
||||||
.with(edn_arg_parser())
|
.with(edn_arg_parser())
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
|
@ -340,15 +320,13 @@ pub fn command(s: &str) -> Result<Command, Error> {
|
||||||
|
|
||||||
spaces()
|
spaces()
|
||||||
.skip(token('.'))
|
.skip(token('.'))
|
||||||
.with(choice::<[&mut Parser<Input = _, Output = Result<Command, Error>>; 16], _>
|
.with(choice::<[&mut Parser<Input = _, Output = Result<Command, Error>>; 14], _>
|
||||||
([&mut try(help_parser),
|
([&mut try(help_parser),
|
||||||
&mut try(import_parser),
|
&mut try(import_parser),
|
||||||
&mut try(timer_parser),
|
&mut try(timer_parser),
|
||||||
&mut try(cache_parser),
|
&mut try(cache_parser),
|
||||||
&mut try(open_encrypted_parser),
|
&mut try(open_encrypted_parser),
|
||||||
&mut try(open_empty_encrypted_parser),
|
|
||||||
&mut try(open_parser),
|
&mut try(open_parser),
|
||||||
&mut try(open_empty_parser),
|
|
||||||
&mut try(close_parser),
|
&mut try(close_parser),
|
||||||
&mut try(explain_query_parser),
|
&mut try(explain_query_parser),
|
||||||
&mut try(exit_parser),
|
&mut try(exit_parser),
|
||||||
|
@ -459,19 +437,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_empty_encrypted_parser() {
|
|
||||||
let input = ".empty_encrypted /path/to/my.db hunter2";
|
|
||||||
let cmd = command(&input).expect("Expected empty_encrypted command");
|
|
||||||
match cmd {
|
|
||||||
Command::OpenEmptyEncrypted(path, key) => {
|
|
||||||
assert_eq!(path, "/path/to/my.db".to_string());
|
|
||||||
assert_eq!(key, "hunter2".to_string());
|
|
||||||
},
|
|
||||||
_ => assert!(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_open_encrypted_parser_missing_key() {
|
fn test_open_encrypted_parser_missing_key() {
|
||||||
let input = ".open_encrypted path/to/db.db";
|
let input = ".open_encrypted path/to/db.db";
|
||||||
|
@ -479,13 +444,6 @@ mod tests {
|
||||||
assert_eq!(err.to_string(), "Missing required argument");
|
assert_eq!(err.to_string(), "Missing required argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_empty_encrypted_parser_missing_key() {
|
|
||||||
let input = ".empty_encrypted path/to/db.db";
|
|
||||||
let err = command(&input).expect_err("Expected an error");
|
|
||||||
assert_eq!(err.to_string(), "Missing required argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sync_parser_path_arg() {
|
fn test_sync_parser_path_arg() {
|
||||||
let input = ".sync https://example.com/api/ 316ea470-ce35-4adf-9c61-e0de6e289c59";
|
let input = ".sync https://example.com/api/ 316ea470-ce35-4adf-9c61-e0de6e289c59";
|
||||||
|
|
|
@ -63,7 +63,6 @@ use command_parser::{
|
||||||
COMMAND_HELP,
|
COMMAND_HELP,
|
||||||
COMMAND_IMPORT_LONG,
|
COMMAND_IMPORT_LONG,
|
||||||
COMMAND_OPEN,
|
COMMAND_OPEN,
|
||||||
COMMAND_OPEN_EMPTY,
|
|
||||||
COMMAND_QUERY_LONG,
|
COMMAND_QUERY_LONG,
|
||||||
COMMAND_QUERY_SHORT,
|
COMMAND_QUERY_SHORT,
|
||||||
COMMAND_QUERY_EXPLAIN_LONG,
|
COMMAND_QUERY_EXPLAIN_LONG,
|
||||||
|
@ -81,7 +80,6 @@ use command_parser::{
|
||||||
// omit them from help message (since they wouldn't work).
|
// omit them from help message (since they wouldn't work).
|
||||||
#[cfg(feature = "sqlcipher")]
|
#[cfg(feature = "sqlcipher")]
|
||||||
use command_parser::{
|
use command_parser::{
|
||||||
COMMAND_OPEN_EMPTY_ENCRYPTED,
|
|
||||||
COMMAND_OPEN_ENCRYPTED,
|
COMMAND_OPEN_ENCRYPTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,12 +105,9 @@ lazy_static! {
|
||||||
(COMMAND_EXIT_SHORT, "Shortcut for `.exit`. Close the current database and exit the REPL."),
|
(COMMAND_EXIT_SHORT, "Shortcut for `.exit`. Close the current database and exit the REPL."),
|
||||||
|
|
||||||
(COMMAND_OPEN, "Open a database at path."),
|
(COMMAND_OPEN, "Open a database at path."),
|
||||||
(COMMAND_OPEN_EMPTY, "Open an empty database at path."),
|
|
||||||
|
|
||||||
#[cfg(feature = "sqlcipher")]
|
#[cfg(feature = "sqlcipher")]
|
||||||
(COMMAND_OPEN_ENCRYPTED, "Open an encrypted database at path using the provided key."),
|
(COMMAND_OPEN_ENCRYPTED, "Open an encrypted database at path using the provided key."),
|
||||||
#[cfg(feature = "sqlcipher")]
|
|
||||||
(COMMAND_OPEN_EMPTY_ENCRYPTED, "Open an empty encrypted database at path using the provided key."),
|
|
||||||
|
|
||||||
(COMMAND_SCHEMA, "Output the schema for the current open database."),
|
(COMMAND_SCHEMA, "Output the schema for the current open database."),
|
||||||
|
|
||||||
|
@ -306,24 +301,12 @@ impl Repl {
|
||||||
Err(e) => eprintln!("{}", e.to_string()),
|
Err(e) => eprintln!("{}", e.to_string()),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
Command::OpenEmpty(db) => {
|
|
||||||
match self.open_empty(db) {
|
|
||||||
Ok(_) => println!("Empty database {:?} opened", self.db_name()),
|
|
||||||
Err(e) => eprintln!("{}", e.to_string()),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
Command::OpenEncrypted(db, encryption_key) => {
|
Command::OpenEncrypted(db, encryption_key) => {
|
||||||
match self.open_with_key(db, &encryption_key) {
|
match self.open_with_key(db, &encryption_key) {
|
||||||
Ok(_) => println!("Database {:?} opened with key {:?}", self.db_name(), encryption_key),
|
Ok(_) => println!("Database {:?} opened with key {:?}", self.db_name(), encryption_key),
|
||||||
Err(e) => eprintln!("{}", e.to_string()),
|
Err(e) => eprintln!("{}", e.to_string()),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Command::OpenEmptyEncrypted(db, encryption_key) => {
|
|
||||||
match self.open_empty_with_key(db, &encryption_key) {
|
|
||||||
Ok(_) => println!("Empty database {:?} opened with key {:?}", self.db_name(), encryption_key),
|
|
||||||
Err(e) => eprintln!("{}", e.to_string()),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Command::Query(query) => {
|
Command::Query(query) => {
|
||||||
self.store
|
self.store
|
||||||
.q_once(query.as_str(), None)
|
.q_once(query.as_str(), None)
|
||||||
|
@ -414,30 +397,20 @@ impl Repl {
|
||||||
|
|
||||||
fn open_common(
|
fn open_common(
|
||||||
&mut self,
|
&mut self,
|
||||||
empty: bool,
|
|
||||||
path: String,
|
path: String,
|
||||||
encryption_key: Option<&str>
|
encryption_key: Option<&str>
|
||||||
) -> ::mentat::errors::Result<()> {
|
) -> ::mentat::errors::Result<()> {
|
||||||
if self.path.is_empty() || path != self.path {
|
if self.path.is_empty() || path != self.path {
|
||||||
let next = match encryption_key {
|
let next = match encryption_key {
|
||||||
#[cfg(not(feature = "sqlcipher"))]
|
#[cfg(not(feature = "sqlcipher"))]
|
||||||
Some(_) => return Err(::mentat::MentatError::RusqliteError(".open_encrypted and .empty_encrypted require the sqlcipher Mentat feature".into())),
|
Some(_) => return Err(::mentat::MentatError::RusqliteError(".open_encrypted requires the sqlcipher Mentat feature".into())),
|
||||||
|
|
||||||
#[cfg(feature = "sqlcipher")]
|
#[cfg(feature = "sqlcipher")]
|
||||||
Some(k) => {
|
Some(k) => {
|
||||||
if empty {
|
|
||||||
Store::open_empty_with_key(path.as_str(), k)?
|
|
||||||
} else {
|
|
||||||
Store::open_with_key(path.as_str(), k)?
|
Store::open_with_key(path.as_str(), k)?
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
if empty {
|
|
||||||
Store::open_empty(path.as_str())?
|
|
||||||
} else {
|
|
||||||
Store::open(path.as_str())?
|
Store::open(path.as_str())?
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.path = path;
|
self.path = path;
|
||||||
self.store = next;
|
self.store = next;
|
||||||
|
@ -447,22 +420,12 @@ impl Repl {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open<T>(&mut self, path: T) -> ::mentat::errors::Result<()> where T: Into<String> {
|
fn open<T>(&mut self, path: T) -> ::mentat::errors::Result<()> where T: Into<String> {
|
||||||
self.open_common(false, path.into(), None)
|
self.open_common(path.into(), None)
|
||||||
}
|
|
||||||
|
|
||||||
fn open_empty<T>(&mut self, path: T)
|
|
||||||
-> ::mentat::errors::Result<()> where T: Into<String> {
|
|
||||||
self.open_common(true, path.into(), None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_with_key<T, U>(&mut self, path: T, encryption_key: U)
|
fn open_with_key<T, U>(&mut self, path: T, encryption_key: U)
|
||||||
-> ::mentat::errors::Result<()> where T: Into<String>, U: AsRef<str> {
|
-> ::mentat::errors::Result<()> where T: Into<String>, U: AsRef<str> {
|
||||||
self.open_common(false, path.into(), Some(encryption_key.as_ref()))
|
self.open_common(path.into(), Some(encryption_key.as_ref()))
|
||||||
}
|
|
||||||
|
|
||||||
fn open_empty_with_key<T, U>(&mut self, path: T, encryption_key: U)
|
|
||||||
-> ::mentat::errors::Result<()> where T: Into<String>, U: AsRef<str> {
|
|
||||||
self.open_common(true, path.into(), Some(encryption_key.as_ref()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the current store by opening a new in-memory store in its place.
|
// Close the current store by opening a new in-memory store in its place.
|
||||||
|
|
Loading…
Reference in a new issue