materialized join cannot be cached

main
Ziyang Hu 2 years ago
parent d1349955b1
commit cea1dc5acc

@ -6,12 +6,9 @@
* You can obtain one at https://mozilla.org/MPL/2.0/. * You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
use std::cell::RefCell;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::iter; use std::iter;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
use either::{Left, Right}; use either::{Left, Right};
use itertools::Itertools; use itertools::Itertools;
@ -474,8 +471,6 @@ impl RelAlgebra {
joiner, joiner,
to_eliminate, to_eliminate,
span, span,
mat_right_cache: RefCell::new(Default::default()),
cached: Default::default(),
})); }));
if !remaining.is_empty() { if !remaining.is_empty() {
joined = RelAlgebra::Filter(FilteredRA { joined = RelAlgebra::Filter(FilteredRA {
@ -521,8 +516,6 @@ impl RelAlgebra {
}, },
to_eliminate: Default::default(), to_eliminate: Default::default(),
span, span,
mat_right_cache: RefCell::new(Default::default()),
cached: Default::default(),
})) }))
} }
pub(crate) fn neg_join( pub(crate) fn neg_join(
@ -1531,8 +1524,6 @@ pub(crate) struct InnerJoin {
pub(crate) joiner: Joiner, pub(crate) joiner: Joiner,
pub(crate) to_eliminate: BTreeSet<Symbol>, pub(crate) to_eliminate: BTreeSet<Symbol>,
pub(crate) span: SourceSpan, pub(crate) span: SourceSpan,
mat_right_cache: RefCell<Rc<Vec<Tuple>>>,
cached: AtomicBool,
} }
impl InnerJoin { impl InnerJoin {
@ -1689,6 +1680,7 @@ impl InnerJoin {
delta_rule: Option<&MagicSymbol>, delta_rule: Option<&MagicSymbol>,
stores: &'a BTreeMap<MagicSymbol, EpochStore>, stores: &'a BTreeMap<MagicSymbol, EpochStore>,
) -> Result<TupleIter<'a>> { ) -> Result<TupleIter<'a>> {
debug!("using materialized join");
let right_bindings = self.right.bindings_after_eliminate(); let right_bindings = self.right.bindings_after_eliminate();
let (left_join_indices, right_join_indices) = self let (left_join_indices, right_join_indices) = self
.joiner .joiner
@ -1716,9 +1708,7 @@ impl InnerJoin {
.sorted_by_key(|(_, b)| **b) .sorted_by_key(|(_, b)| **b)
.map(|(a, _)| a) .map(|(a, _)| a)
.collect_vec(); .collect_vec();
let cached_data = if self.cached.load(Ordering::Relaxed) { let cached_data = {
self.mat_right_cache.borrow().clone()
} else {
let mut cache = BTreeSet::new(); let mut cache = BTreeSet::new();
for item in self.right.iter(tx, delta_rule, stores)? { for item in self.right.iter(tx, delta_rule, stores)? {
match item { match item {
@ -1732,10 +1722,7 @@ impl InnerJoin {
Err(e) => return Err(e), Err(e) => return Err(e),
} }
} }
let cache = cache.into_iter().collect_vec(); cache.into_iter().collect_vec()
*self.mat_right_cache.borrow_mut() = Rc::new(cache);
self.cached.store(true, Ordering::Relaxed);
self.mat_right_cache.borrow().clone()
}; };
let (prefix, right_idx) = let (prefix, right_idx) =
@ -1756,7 +1743,7 @@ impl InnerJoin {
} }
struct CachedMaterializedIterator<'a> { struct CachedMaterializedIterator<'a> {
materialized: Rc<Vec<Tuple>>, materialized: Vec<Tuple>,
eliminate_indices: BTreeSet<usize>, eliminate_indices: BTreeSet<usize>,
left_join_indices: Vec<usize>, left_join_indices: Vec<usize>,
right_invert_indices: Vec<usize>, right_invert_indices: Vec<usize>,

@ -1293,4 +1293,18 @@ mod tests {
.rows; .rows;
assert_eq!(res[0][0], json!(1.1)) assert_eq!(res[0][0], json!(1.1))
} }
#[test]
fn test_classical() {
let _ = env_logger::builder().is_test(true).try_init();
let db = new_cozo_mem().unwrap();
let res = db.run_script(r#"
parent[] <- [['joseph', 'jakob'],
['jakob', 'issac'],
['issac', 'abraham']]
grandparent[gcld, gp] := parent[gcld, p], parent[p, gp]
?[who] := grandparent[who, 'abraham']
"#, Default::default()).unwrap().rows;
println!("{:?}", res);
assert_eq!(res[0][0], json!("jakob"))
}
} }

@ -224,19 +224,15 @@ function App() {
Please refer to the <a href="https://github.com/cozodb/cozo/">project homepage</a> for Please refer to the <a href="https://github.com/cozodb/cozo/">project homepage</a> for
more information about the Cozo database. more information about the Cozo database.
</p> </p>
<h2>Not sure what to run? Click/touch <a onClick={() => { <h2>Not sure what to run?</h2>
setQueryText(`love[loving, loved] <- [['alice', 'eve'], ['bob', 'alice'],
['eve', 'alice'], ['eve', 'bob'],
['eve', 'charlie'], ['charlie', 'eve'],
['david', 'george'], ['george', 'george']]
cls[loving, loved] := love[loving, loved]
cls[loving, loved] := cls[loving, middle], love[middle, loved]
?[loving, loved] := cls[loving, loved]`)
}}>HERE</a> ...</h2>
<p> <p>
... and run the script, to compute the <a <a onClick={() => {
href="https://en.wikipedia.org/wiki/Transitive_closure">transitive closure</a> of setQueryText(`parent[] <- [['joseph', 'jakob'],
a hypothetical love triangle. ['jakob', 'issac'],
['issac', 'abraham']]
grandparent[gcld, gp] := parent[gcld, p], parent[p, gp]
?[who] := grandparent[who, 'abraham']`)
}}>Here</a> is a classical example recursive example.
</p> </p>
<p> <p>
The <a href="https://github.com/cozodb/cozo-docs/blob/main/tutorial/tutorial.ipynb">tutorial</a> contains many more examples. The <a href="https://github.com/cozodb/cozo-docs/blob/main/tutorial/tutorial.ipynb">tutorial</a> contains many more examples.

Loading…
Cancel
Save