From ab8d1e25b713278496a6e1262c05bb766f7a09d3 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 9 Jul 2024 05:13:09 +0700 Subject: [PATCH] more work --- grovedb/src/operations/proof/generate.rs | 2 +- grovedb/src/query/mod.rs | 90 +++++++++++++++++++++++- grovedb/src/tests/query_tests.rs | 4 +- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/grovedb/src/operations/proof/generate.rs b/grovedb/src/operations/proof/generate.rs index d19a3061..73f8d89d 100644 --- a/grovedb/src/operations/proof/generate.rs +++ b/grovedb/src/operations/proof/generate.rs @@ -406,7 +406,7 @@ impl GroveDb { if !done_with_results && query.has_subquery_or_matching_in_path_on_key(key) => { - println!("found tree {}, query is {:?}", hex_to_ascii(key), query); + println!("found tree {}, query is {}", hex_to_ascii(key), query); // We only want to check in sub nodes for the proof if the tree has // elements let mut lower_path = path.clone(); diff --git a/grovedb/src/query/mod.rs b/grovedb/src/query/mod.rs index fa54f971..c395d7e3 100644 --- a/grovedb/src/query/mod.rs +++ b/grovedb/src/query/mod.rs @@ -312,8 +312,7 @@ impl PathQuery { } } else { let last_path_item = path.len() == subquery_path.len(); - let has_subquery = - query.default_subquery_branch.subquery.is_some(); + let has_subquery = subquery_branch.subquery.is_some(); Some(InternalCowItemsQuery::from_key_when_in_path( &subquery_path[path_after_top_removed.len()], last_path_item, @@ -422,6 +421,23 @@ pub(crate) enum HasSubquery<'a> { Conditionally(Cow<'a, IndexMap>), } +#[cfg(any(feature = "full", feature = "verify"))] +impl<'a> fmt::Display for HasSubquery<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + HasSubquery::NoSubquery => write!(f, "NoSubquery"), + HasSubquery::Always => write!(f, "Always"), + HasSubquery::Conditionally(map) => { + writeln!(f, "Conditionally {{")?; + for (query_item, subquery_branch) in map.iter() { + writeln!(f, " {query_item}: {subquery_branch},")?; + } + write!(f, "}}") + } + } + } +} + impl<'a> HasSubquery<'a> { /// Checks to see if we have a subquery on a specific key pub fn has_subquery_on_key(&self, key: &[u8]) -> bool { @@ -450,6 +466,25 @@ pub(crate) struct InternalCowItemsQuery<'a> { pub in_path: Option>, } +#[cfg(any(feature = "full", feature = "verify"))] +impl<'a> fmt::Display for InternalCowItemsQuery<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "InternalCowItemsQuery {{")?; + writeln!(f, " items: [")?; + for item in self.items.iter() { + writeln!(f, " {item},")?; + } + writeln!(f, " ]")?; + writeln!(f, " has_subquery: {}", self.has_subquery)?; + writeln!(f, " left_to_right: {}", self.left_to_right)?; + match &self.in_path { + Some(path) => writeln!(f, " in_path: Some({})", hex_to_ascii(&path)), + None => writeln!(f, " in_path: None"), + }?; + write!(f, "}}") + } +} + impl<'a> InternalCowItemsQuery<'a> { /// Checks to see if we have a subquery on a specific key pub fn has_subquery_on_key(&self, key: &[u8]) -> bool { @@ -521,6 +556,7 @@ mod tests { query::{query_item::QueryItem, SubqueryBranch}, Query, }; + use indexmap::IndexMap; use crate::{ query::{HasSubquery, InternalCowItemsQuery}, @@ -1352,4 +1388,54 @@ mod tests { ); } } + + #[test] + fn test_conditional_subquery_refusing_elements() { + let empty_vec: Vec = vec![]; + let zero_vec: Vec = vec![0]; + + let mut conditional_subquery_branches = IndexMap::new(); + conditional_subquery_branches.insert( + QueryItem::Key(b"".to_vec()), + SubqueryBranch { + subquery_path: Some(vec![zero_vec.clone()]), + subquery: Some(Query::new().into()), + }, + ); + + let path_query = PathQuery { + path: vec![TEST_LEAF.to_vec()], + query: SizedQuery { + query: Query { + items: vec![QueryItem::RangeFull(RangeFull)], + default_subquery_branch: SubqueryBranch { + subquery_path: Some(vec![zero_vec.clone()]), + subquery: None, + }, + left_to_right: true, + conditional_subquery_branches: Some(conditional_subquery_branches), + }, + limit: Some(100), + offset: None, + }, + }; + + { + let path = vec![TEST_LEAF, empty_vec.as_slice()]; + + let second = path_query + .query_items_at_path(&path) + .expect("expected query items"); + + assert_eq!( + second, + InternalCowItemsQuery { + items: Cow::Owned(vec![QueryItem::Key(zero_vec.clone())]), + has_subquery: HasSubquery::NoSubquery, + left_to_right: true, + in_path: Some(Cow::Borrowed(&zero_vec)), + } + ); + } + } } diff --git a/grovedb/src/tests/query_tests.rs b/grovedb/src/tests/query_tests.rs index a9503a5e..2427abd3 100644 --- a/grovedb/src/tests/query_tests.rs +++ b/grovedb/src/tests/query_tests.rs @@ -561,9 +561,11 @@ mod tests { let subquery = Query::new(); + // This conditional subquery expresses that we do not want to get values in "" + // tree query.add_conditional_subquery( QueryItem::Key(b"".to_vec()), - Some(vec![b"\0".to_vec()]), + Some(vec![b"\0".to_vec()]), // We want to go into 0 but we don't want to get anything Some(subquery), );