Skip to content

Commit

Permalink
implement SPARQL Union
Browse files Browse the repository at this point in the history
  • Loading branch information
pchampin committed Nov 22, 2024
1 parent f7985ab commit 258ac21
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
27 changes: 26 additions & 1 deletion sparql/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl<'a, D: Dataset + ?Sized> ExecState<'a, D> {
expression,
} => Err(SparqlWrapperError::NotImplemented("LeftJoin")),
Filter { expr, inner } => self.filter(expr, inner, graph_matcher, binding),
Union { left, right } => Err(SparqlWrapperError::NotImplemented("Union")),
Union { left, right } => self.union(left, right, graph_matcher, binding),
Graph { name, inner } => Err(SparqlWrapperError::NotImplemented("Graph")),
Extend {
inner,
Expand Down Expand Up @@ -184,6 +184,31 @@ impl<'a, D: Dataset + ?Sized> ExecState<'a, D> {
Ok(Bindings { variables, iter })
}

fn union(
&mut self,
left: &GraphPattern,
right: &GraphPattern,
graph_matcher: &[Option<ArcTerm>],
binding: Option<&Binding>,
) -> Result<Bindings<'a, D>, SparqlWrapperError<D::Error>> {
let Bindings {
variables: lv,
iter: li,
} = self.select(left, graph_matcher, binding)?;
let Bindings {
variables: rv,
iter: ri,
} = self.select(right, graph_matcher, binding)?;
let mut variables = lv.clone();
for v in rv {
if lv.iter().all(|i| *i != v) {
variables.push(v)
}
}
let iter = Box::new(li.chain(ri));
Ok(Bindings { variables, iter })
}

fn extend(
&mut self,
inner: &GraphPattern,
Expand Down
38 changes: 38 additions & 0 deletions sparql/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ use test_case::test_case;
vec![];
"no result"
)]
#[test_case(
"PREFIX s: <http://schema.org/> SELECT ?x { { ?x a s:Event } UNION { ?x a s:Person } }",
vec!["<https://example.org/test#a>", "_:b"];
"union"
)]
fn test_select_1_and_ask(query: &str, exp: Vec<&str>) -> TestResult {
let dataset = dataset_101()?;
let dataset = SparqlWrapper(&dataset);
Expand All @@ -35,6 +40,39 @@ fn test_select_1_and_ask(query: &str, exp: Vec<&str>) -> TestResult {
Ok(())
}

#[test]
fn test_union() -> TestResult {
let dataset = dataset_101()?;
let dataset = SparqlWrapper(&dataset);
let parsed_query = SparqlQuery::parse(
r"
PREFIX s: <http://schema.org/>
SELECT ?p ?e {
{ ?p a s:Person }
UNION
{ ?e a s:Event }
}
",
)?;
let bindings = dataset.query(&parsed_query)?.into_bindings();
assert_eq!(bindings.variables(), &["p", "e"]);
let mut got = bindings.into_iter().collect::<Result<Vec<_>, _>>()?;
got.sort();
assert_eq!(got.len(), 2);
assert_eq!(got[0].len(), 2);
assert!(got[0][0].is_none());
assert!(got[0][1].is_some());
assert!(got[0][1].as_ref().unwrap().is_blank_node());
assert!(got[1][0].is_some());
assert!(got[1][0].as_ref().unwrap().is_iri());
assert_eq!(
got[1][0].as_ref().unwrap().to_string(),
"<https://example.org/test#a>"
);
assert!(got[1][1].is_none());
Ok(())
}

#[test_case(1)]
#[test_case(2)]
#[test_case(3)]
Expand Down

0 comments on commit 258ac21

Please sign in to comment.