Skip to content

Commit d53553a

Browse files
committed
improving intersect and adding tests
1 parent 4a49263 commit d53553a

File tree

4 files changed

+45
-29
lines changed

4 files changed

+45
-29
lines changed

helix-db/src/helix_engine/tests/traversal_tests/intersect_tests.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ fn test_intersect_user_scenario() {
141141
.intersect(|val, db, txn, arena| {
142142
G::from_iter(db, txn, std::iter::once(val), arena)
143143
.out_node("links")
144-
.filter_map(|r| r.ok())
145-
.collect::<Vec<_>>()
144+
.collect::<Result<Vec<_>, _>>()
146145
})
147146
.collect::<Result<Vec<_>, _>>()
148147
.unwrap();
@@ -230,8 +229,7 @@ fn test_intersect_basic() {
230229
.intersect(|val, db, txn, arena| {
231230
G::from_iter(db, txn, std::iter::once(val), arena)
232231
.out_node("rel")
233-
.filter_map(|r| r.ok())
234-
.collect::<Vec<_>>()
232+
.collect::<Result<Vec<_>, _>>()
235233
})
236234
.collect::<Result<Vec<_>, _>>()
237235
.unwrap();
@@ -295,8 +293,7 @@ fn test_intersect_empty_result() {
295293
.intersect(|val, db, txn, arena| {
296294
G::from_iter(db, txn, std::iter::once(val), arena)
297295
.out_node("rel")
298-
.filter_map(|r| r.ok())
299-
.collect::<Vec<_>>()
296+
.collect::<Result<Vec<_>, _>>()
300297
})
301298
.collect::<Result<Vec<_>, _>>()
302299
.unwrap();
@@ -351,8 +348,7 @@ fn test_intersect_single_upstream() {
351348
.intersect(|val, db, txn, arena| {
352349
G::from_iter(db, txn, std::iter::once(val), arena)
353350
.out_node("rel")
354-
.filter_map(|r| r.ok())
355-
.collect::<Vec<_>>()
351+
.collect::<Result<Vec<_>, _>>()
356352
})
357353
.collect::<Result<Vec<_>, _>>()
358354
.unwrap();
@@ -386,8 +382,7 @@ fn test_intersect_empty_upstream() {
386382
.intersect(|val, db, txn, arena| {
387383
G::from_iter(db, txn, std::iter::once(val), arena)
388384
.out_node("rel")
389-
.filter_map(|r| r.ok())
390-
.collect::<Vec<_>>()
385+
.collect::<Result<Vec<_>, _>>()
391386
})
392387
.collect::<Result<Vec<_>, _>>()
393388
.unwrap();
@@ -445,8 +440,7 @@ fn test_intersect_all_same_targets() {
445440
.intersect(|val, db, txn, arena| {
446441
G::from_iter(db, txn, std::iter::once(val), arena)
447442
.out_node("rel")
448-
.filter_map(|r| r.ok())
449-
.collect::<Vec<_>>()
443+
.collect::<Result<Vec<_>, _>>()
450444
})
451445
.collect::<Result<Vec<_>, _>>()
452446
.unwrap();
@@ -521,8 +515,7 @@ fn test_intersect_one_upstream_has_no_edges() {
521515
.intersect(|val, db, txn, arena| {
522516
G::from_iter(db, txn, std::iter::once(val), arena)
523517
.out_node("rel")
524-
.filter_map(|r| r.ok())
525-
.collect::<Vec<_>>()
518+
.collect::<Result<Vec<_>, _>>()
526519
})
527520
.collect::<Result<Vec<_>, _>>()
528521
.unwrap();
@@ -607,8 +600,7 @@ fn test_intersect_with_in_edges() {
607600
.intersect(|val, db, txn, arena| {
608601
G::from_iter(db, txn, std::iter::once(val), arena)
609602
.in_node("points_to")
610-
.filter_map(|r| r.ok())
611-
.collect::<Vec<_>>()
603+
.collect::<Result<Vec<_>, _>>()
612604
})
613605
.collect::<Result<Vec<_>, _>>()
614606
.unwrap();

helix-db/src/helix_engine/traversal_core/ops/util/intersect.rs

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub trait IntersectAdapter<'db, 'arena, 'txn>: Iterator {
2727
&'db HelixGraphStorage,
2828
&'txn RoTxn<'db>,
2929
&'arena bumpalo::Bump,
30-
) -> Vec<TraversalValue<'arena>>;
30+
) -> Result<Vec<TraversalValue<'arena>>, GraphError>;
3131
}
3232

3333
impl<'db, 'arena, 'txn, I: Iterator<Item = Result<TraversalValue<'arena>, GraphError>>>
@@ -48,17 +48,27 @@ impl<'db, 'arena, 'txn, I: Iterator<Item = Result<TraversalValue<'arena>, GraphE
4848
&'db HelixGraphStorage,
4949
&'txn RoTxn<'db>,
5050
&'arena bumpalo::Bump,
51-
) -> Vec<TraversalValue<'arena>>,
51+
) -> Result<Vec<TraversalValue<'arena>>, GraphError>,
5252
{
5353
let storage = self.storage;
5454
let txn = self.txn;
5555
let arena = self.arena;
5656

57-
// Collect all upstream items
58-
let upstream: Vec<TraversalValue<'arena>> = self
59-
.inner
60-
.filter_map(|item| item.ok())
61-
.collect();
57+
// Collect all upstream items, propagating errors
58+
let mut upstream: Vec<TraversalValue<'arena>> = Vec::new();
59+
for item in self.inner {
60+
match item {
61+
Ok(val) => upstream.push(val),
62+
Err(e) => {
63+
return RoTraversalIterator {
64+
storage,
65+
arena,
66+
txn,
67+
inner: vec![Err(e)].into_iter(),
68+
};
69+
}
70+
}
71+
}
6272

6373
if upstream.is_empty() {
6474
return RoTraversalIterator {
@@ -69,11 +79,21 @@ impl<'db, 'arena, 'txn, I: Iterator<Item = Result<TraversalValue<'arena>, GraphE
6979
};
7080
}
7181

72-
// Run all sub-traversals
73-
let mut all_results: Vec<Vec<TraversalValue<'arena>>> = upstream
74-
.into_iter()
75-
.map(|item| f(item, storage, txn, arena))
76-
.collect();
82+
// Run all sub-traversals, propagating errors
83+
let mut all_results: Vec<Vec<TraversalValue<'arena>>> = Vec::new();
84+
for item in upstream {
85+
match f(item, storage, txn, arena) {
86+
Ok(results) => all_results.push(results),
87+
Err(e) => {
88+
return RoTraversalIterator {
89+
storage,
90+
arena,
91+
txn,
92+
inner: vec![Err(e)].into_iter(),
93+
};
94+
}
95+
}
96+
}
7797

7898
// Sort by size — smallest first so intersection shrinks fastest
7999
all_results.sort_by_key(|r| r.len());

helix-db/src/helixc/generator/traversal_steps.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1365,7 +1365,7 @@ impl Display for Intersect {
13651365
"intersect(|val, db, txn, arena| {{\
13661366
G::from_iter(&db, &txn, std::iter::once(val), &arena)\
13671367
{}\
1368-
.filter_map(|r| r.ok()).collect::<Vec<_>>()\
1368+
.collect::<Result<Vec<_>, _>>()\
13691369
}})",
13701370
self.traversal.format_steps_only()
13711371
)

hql-tests/tests/intersect/queries.hx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ QUERY TagArticle(article_id: ID, tag_id: ID) =>
1414
QUERY ArticlesByAllTags(tag_names: [String]) =>
1515
articles <- N<Tag>::WHERE(_::{name}::IS_IN(tag_names))::INTERSECT(_::In<HasTag>)
1616
RETURN articles
17+
18+
QUERY ArticlesByAllTagsTitle(tag_names: [String],name: String) =>
19+
articles <- N<Tag>::WHERE(_::{name}::IS_IN(tag_names))::INTERSECT(_::In<HasTag>)::WHERE(_::{title}::EQ(name))
20+
RETURN articles

0 commit comments

Comments
 (0)