diff --git a/Cargo.lock b/Cargo.lock index a6a399be..82546fae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -697,7 +697,7 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cozo" -version = "0.7.3" +version = "0.7.4" dependencies = [ "aho-corasick", "approx", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "cozo-bin" -version = "0.7.3" +version = "0.7.4" dependencies = [ "async-stream", "axum", @@ -787,7 +787,7 @@ dependencies = [ [[package]] name = "cozo-lib-wasm" -version = "0.7.3" +version = "0.7.4" dependencies = [ "console_error_panic_hook", "cozo", @@ -798,7 +798,7 @@ dependencies = [ [[package]] name = "cozo-node" -version = "0.7.3" +version = "0.7.4" dependencies = [ "cozo", "crossbeam", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "cozo-swift" -version = "0.7.3" +version = "0.7.4" dependencies = [ "cozo", "swift-bridge", @@ -819,7 +819,7 @@ dependencies = [ [[package]] name = "cozo_c" -version = "0.7.3" +version = "0.7.4" dependencies = [ "cbindgen", "cozo", @@ -828,7 +828,7 @@ dependencies = [ [[package]] name = "cozo_java" -version = "0.7.3" +version = "0.7.4" dependencies = [ "cozo", "jni", @@ -837,7 +837,7 @@ dependencies = [ [[package]] name = "cozo_py" -version = "0.7.3" +version = "0.7.4" dependencies = [ "cozo", "miette", diff --git a/cozo-core/src/query/ra.rs b/cozo-core/src/query/ra.rs index 576dd91f..5056f88a 100644 --- a/cozo-core/src/query/ra.rs +++ b/cozo-core/src/query/ra.rs @@ -1263,73 +1263,44 @@ impl StoredRA { key_len: usize, left_to_prefix_indices: Vec, eliminate_indices: BTreeSet, - left_tuple_len: usize, + left_join_indices: Vec, + right_join_indices: Vec, ) -> Result> { - let val_len = self.storage.metadata.non_keys.len(); - let all_right_val_indices: BTreeSet = - (0..val_len).map(|i| left_tuple_len + key_len + i).collect(); let mut stack = vec![]; - if self.filters.is_empty() && eliminate_indices.is_superset(&all_right_val_indices) { - let it = left_iter - .map_ok(move |tuple| -> Result> { - let prefix = left_to_prefix_indices - .iter() - .map(|i| tuple[*i].clone()) - .collect_vec(); - let key = &prefix[0..key_len]; - for (p, span) in self.filters_bytecodes.iter() { - if !eval_bytecode_pred(p, key, &mut stack, *span)? { - return Ok(None); + + let it = left_iter + .map_ok(move |tuple| -> Result> { + let prefix = left_to_prefix_indices + .iter() + .map(|i| tuple[*i].clone()) + .collect_vec(); + let key = &prefix[0..key_len]; + match self.storage.get(tx, key)? { + None => Ok(None), + Some(found) => { + for (lk, rk) in left_join_indices.iter().zip(right_join_indices.iter()) { + if tuple[*lk] != found[*rk] { + return Ok(None); + } } - } - if self.storage.exists(tx, key)? { - let mut ret = tuple; - ret.extend_from_slice(key); - for _ in 0..val_len { - ret.push(DataValue::Bot); + for (p, span) in self.filters_bytecodes.iter() { + if !eval_bytecode_pred(p, &found, &mut stack, *span)? { + return Ok(None); + } } + let mut ret = tuple; + ret.extend(found); Ok(Some(ret)) - } else { - Ok(None) } - }) - .flatten_ok() - .filter_map(invert_option_err); - Ok(if eliminate_indices.is_empty() { - Box::new(it) - } else { - Box::new(it.map_ok(move |t| eliminate_from_tuple(t, &eliminate_indices))) + } }) + .flatten_ok() + .filter_map(invert_option_err); + Ok(if eliminate_indices.is_empty() { + Box::new(it) } else { - let it = left_iter - .map_ok(move |tuple| -> Result> { - let prefix = left_to_prefix_indices - .iter() - .map(|i| tuple[*i].clone()) - .collect_vec(); - let key = &prefix[0..key_len]; - match self.storage.get(tx, key)? { - None => Ok(None), - Some(found) => { - for (p, span) in self.filters_bytecodes.iter() { - if !eval_bytecode_pred(p, &found, &mut stack, *span)? { - return Ok(None); - } - } - let mut ret = tuple; - ret.extend(found); - Ok(Some(ret)) - } - } - }) - .flatten_ok() - .filter_map(invert_option_err); - Ok(if eliminate_indices.is_empty() { - Box::new(it) - } else { - Box::new(it.map_ok(move |t| eliminate_from_tuple(t, &eliminate_indices))) - }) - } + Box::new(it.map_ok(move |t| eliminate_from_tuple(t, &eliminate_indices))) + }) } fn prefix_join<'a>( @@ -1338,7 +1309,6 @@ impl StoredRA { left_iter: TupleIter<'a>, (left_join_indices, right_join_indices): (Vec, Vec), eliminate_indices: BTreeSet, - left_tuple_len: usize, ) -> Result> { let mut right_invert_indices = right_join_indices.iter().enumerate().collect_vec(); right_invert_indices.sort_by_key(|(_, b)| **b); @@ -1355,7 +1325,8 @@ impl StoredRA { key_len, left_to_prefix_indices, eliminate_indices, - left_tuple_len, + left_join_indices, + right_join_indices, ); } @@ -2200,13 +2171,11 @@ impl InnerJoin { ) .unwrap(); if join_is_prefix(&join_indices.1) { - let left_len = self.left.bindings_after_eliminate().len(); r.prefix_join( tx, self.left.iter(tx, delta_rule, stores)?, join_indices, eliminate_indices, - left_len, ) } else { self.materialized_join(tx, eliminate_indices, delta_rule, stores) diff --git a/cozo-core/src/runtime/tests.rs b/cozo-core/src/runtime/tests.rs index b4898299..1a506edd 100644 --- a/cozo-core/src/runtime/tests.rs +++ b/cozo-core/src/runtime/tests.rs @@ -905,6 +905,22 @@ fn test_lsh_indexing3() { } } +#[test] +fn filtering() { + let db = DbInstance::default(); + let res = db.run_default(r" + { + ?[x, y] <- [[1, 2]] + :create _rel {x => y} + :returning + } + { + ?[x, y] := x = 1, *_rel{x, y: 3}, y = 2 + } + ") + .unwrap(); + assert_eq!(0, res.rows.len()); +} #[test] fn test_lsh_indexing4() {