diff --git a/grovedb/src/lib.rs b/grovedb/src/lib.rs index 41d980832..afc677c68 100644 --- a/grovedb/src/lib.rs +++ b/grovedb/src/lib.rs @@ -212,6 +212,21 @@ impl GroveDb { Ok(()) } + pub fn insert_if_not_exists( + &mut self, + path: &[&[u8]], + key: Vec, + element: subtree::Element, + ) -> Result { + if self.get(path, &key).is_ok() { + return Ok(false); + } + match self.insert(path, key, element) { + Ok(_) => Ok(true), + Err(e) => Err(e), + } + } + pub fn get(&self, path: &[&[u8]], key: &[u8]) -> Result { match self.get_raw(path, key)? { Element::Reference(reference_path) => self.follow_reference(reference_path), diff --git a/grovedb/src/tests.rs b/grovedb/src/tests.rs index 4b92ce4d8..795b2b20f 100644 --- a/grovedb/src/tests.rs +++ b/grovedb/src/tests.rs @@ -315,3 +315,28 @@ fn test_checkpoint() { Err(Error::InvalidPath(_)) )); } + +#[test] +fn test_insert_if_not_exists() { + let mut db = make_grovedb(); + + // Insert twice at the same path + assert_eq!( + db.insert_if_not_exists(&[TEST_LEAF], b"key1".to_vec(), Element::empty_tree()) + .expect("Provided valid path"), + true + ); + assert_eq!( + db.insert_if_not_exists(&[TEST_LEAF], b"key1".to_vec(), Element::empty_tree()) + .expect("Provided valid path"), + false + ); + + // Should propagate errors from insertion + let result = db.insert_if_not_exists( + &[TEST_LEAF, b"unknown"], + b"key1".to_vec(), + Element::empty_tree(), + ); + assert!(matches!(result, Err(Error::InvalidPath(_)))); +}