diff --git a/lattices/src/ght.rs b/lattices/src/ght.rs index e0a56861fb5e..787e6b8d617c 100644 --- a/lattices/src/ght.rs +++ b/lattices/src/ght.rs @@ -473,7 +473,7 @@ where } #[sealed] -/// iterators for HashTries based on a prefix search +/// iterators for GHTs based on a prefix search pub trait GhtPrefixIter { /// the schema output type Item: VariadicExt; @@ -528,7 +528,7 @@ where } } -/// This case only splits HEAD and REST in order to prevent a conflict with the `HtPrefixIter` impl. +/// This case splits KeyPrefixRef and ValType in order to prevent a conflict with the `GhtPrefixIter` impl. /// If not for that, we could just use a single variadic type parameter. #[sealed] impl GhtPrefixIter diff --git a/lattices/src/ght_lazy.rs b/lattices/src/ght_lazy.rs index cefee30dde36..ed05b99d4aa2 100644 --- a/lattices/src/ght_lazy.rs +++ b/lattices/src/ght_lazy.rs @@ -9,16 +9,19 @@ use variadics::{ use crate::ght::{GeneralizedHashTrieNode, GhtGet, GhtInner, GhtLeaf}; -// Strategies for Get on a ColtNode: -// 1. ColtNode returns different type for var_type!(GhtInner>) (drops First). -// THIS IS WHAT WE IMPLEMENTED -// 2. Somehow cast the prefix of Nones on each call to have Head = ColtNode::Reverse::Car::Head -// Problem: messy -// 3. Walk the tries in the forest sequentially (with a height parameter) -// Seems less efficient/elegant - #[sealed] /// COLT from Wang/Willsey/Suciu +/// In the paper, the COLT is an unbalanced trie that "grows upward" from leaves via the +/// `force` method. Unbalanced tries don't interact well with our Rust types, which want +/// a node's type to be defined via the type of its children, recursively -- +/// that means all paths need to be the same length! +/// +/// To work around this, our COLT is a forest of balanced GHTs of increasing height, from 0 to the number of columns +/// in the key - 1. Instead of the `force` method lengthening the path above a leaf by 1, it +/// instead `take`s the leaf from the current trie and merges it in to the trie to the right which +/// is 1 taller. + +/// A trait for the special behavior we need from the GHTs in a COLT forest pub trait ColumnLazyTrieNode: GeneralizedHashTrieNode { /// into_iter for leaf elements, needed by force below fn into_iter(self) -> Option>; @@ -117,7 +120,7 @@ where #[macro_export] /// Constructs a forest (variadic list) of Ght structs, -/// one for each height from 1 to length of the schema +/// one for each height from 0 to length of the schema - 1 macro_rules! GhtForestType { ($a:ty, $( $b:ty ),* => ()) => { var_type!($crate::GhtType!($a, $( $b ),* => (): Column)) @@ -286,10 +289,10 @@ where } /// Virtual COLT "node" with an API similar to GeneralizedHashTrieNode. -/// This is basically a GhtForest of subtries, with each subtrie wrapped -/// in Option<&'_ Subtrie>. The Option is there because the `get`s from the root(s) -/// that led us to these subtries may have encountered no match in some of the tries -/// in the forest; those tries are None now. +/// The "current node" at depth d from the root in the Wang/Willsey/Suciu +/// paper sits above an unbalanced trie. We emulate that here via a variadic +/// of nodes at depth d in all the tries in the forest (that are height d or taller.) +/// This is basically a GhtForest of subtries. #[sealed] pub trait ColtNode { /// Schema variadic: the schema of the relation stored in this COLT. @@ -505,29 +508,8 @@ where } } -// #[sealed] -// impl<'a, Schema, ValType> ColtNode for var_type!(Option<&'a mut GhtLeaf>) -// where -// GhtLeaf: GeneralizedHashTrieNode + GhtGet, -// ValType: Clone + Eq + Hash, -// { -// type Schema = Schema; -// type SuffixSchema = ValType; -// type Head = as GeneralizedHashTrieNode>::Head; -// type Get = var_type!(Option<&'a mut as GhtGet>::Get>); - -// fn get_broken(self, head: &GhtKey) -> Self::Get { -// var_expr!(self.0.unwrap().get_mut(head)) -// } - -// fn get(self, head: &GhtKey) -> Self::Get { -// // var_expr!(self.0.unwrap().get_mut(head)) -// var_expr!(self.0.and_then(|x| x.get_mut(head))) -// } -// } - // THE CODE BELOW MAY NOT BE USEFUL -/// Make a GhtForest trait with a force method that does the forcing+merging logic +/// A GhtForest trait with a force method that does the forcing+merging logic /// This trait will be recursive on the variadic of `Ght`s. #[sealed] pub trait GhtForest @@ -538,7 +520,7 @@ where /// if it finds such a trie, and the search_key is longer than the height, /// it will force the leaf into the next trie over and recurse. /// returns true if it forces (1 or more times), and false otherwise. - fn force(&mut self, search_key: SearchKey) -> bool; + fn find_and_force(&mut self, search_key: SearchKey) -> bool; } #[sealed] @@ -560,7 +542,7 @@ where TrieFirst::Storage, >: ColumnLazyTrieNode, { - fn force<'a>(&mut self, search_key: SearchKey) -> bool { + fn find_and_force<'a>(&mut self, search_key: SearchKey) -> bool { let var_expr!(first, ...rest) = self; //.forest; if first.height() < SearchKey::LEN { let (row, _): ( @@ -582,7 +564,9 @@ where // drop through and recurse: we may have to force again in the neighbor } // recurse - >::force(rest, search_key) + >::find_and_force( + rest, search_key, + ) } else { false } @@ -596,7 +580,7 @@ where SearchKey: VariadicExt, TrieFirst: GeneralizedHashTrieNode, { - fn force<'a>(&mut self, _search_key: SearchKey) -> bool { + fn find_and_force<'a>(&mut self, _search_key: SearchKey) -> bool { false } } @@ -606,7 +590,7 @@ impl GhtForest for var_type!() where SearchKey: VariadicExt, { - fn force<'a>(&mut self, _search_key: SearchKey) -> bool { + fn find_and_force<'a>(&mut self, _search_key: SearchKey) -> bool { false } } diff --git a/lattices/src/ght_test.rs b/lattices/src/ght_test.rs index 8b042af6a59c..1ffb10a66e23 100644 --- a/lattices/src/ght_test.rs +++ b/lattices/src/ght_test.rs @@ -1002,11 +1002,20 @@ mod test { forest.0.insert(var_expr!(2, 2, 2, 2)); forest.0.insert(var_expr!(3, 3, 3, 3)); - GhtForest::::force(&mut forest, var_expr!(1, 1, 1, 1)); + GhtForest::::find_and_force( + &mut forest, + var_expr!(1, 1, 1, 1), + ); println!("Forest after forcing (1, 1, 1, 1): {:?}", forest); - GhtForest::::force(&mut forest, var_expr!(2, 1, 1, 1)); + GhtForest::::find_and_force( + &mut forest, + var_expr!(2, 1, 1, 1), + ); println!("Forest after forcing (2, 1, 1, 1): {:?}", forest); - GhtForest::::force(&mut forest, var_expr!(3, 3, 3, 3)); + GhtForest::::find_and_force( + &mut forest, + var_expr!(3, 3, 3, 3), + ); println!("Forest after forcing (3, 3, 3, 3): {:?}", forest); println!(