From 5284ac7228155087117806ca31147b33dba2a397 Mon Sep 17 00:00:00 2001 From: Tpt Date: Fri, 21 Oct 2022 14:47:30 +0200 Subject: [PATCH] Variable should stay not bound in subqueries even if they are bound in the parent query Closes #261 --- lib/src/sparql/eval.rs | 43 +++++++++++-------- testsuite/oxigraph-tests/sparql/manifest.ttl | 7 +++ .../sparql/unbound_variable_in_subquery.rq | 6 +++ .../sparql/unbound_variable_in_subquery.srx | 17 ++++++++ 4 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.rq create mode 100644 testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.srx diff --git a/lib/src/sparql/eval.rs b/lib/src/sparql/eval.rs index 4f2d031c..87a803a5 100644 --- a/lib/src/sparql/eval.rs +++ b/lib/src/sparql/eval.rs @@ -531,23 +531,32 @@ impl SimpleEvaluator { let mapping = mapping.clone(); Rc::new(move |from| { let mapping = mapping.clone(); - // We map forward the "from" values to make sure we join wit them - let mut inner_from = EncodedTuple::with_capacity(mapping.len()); - for (input_key, output_key) in mapping.iter() { - if let Some(value) = from.get(*output_key) { - inner_from.set(*input_key, value.clone()); - } - } - Box::new(child(inner_from).map(move |tuple| { - let tuple = tuple?; - let mut output_tuple = from.clone(); - for (input_key, output_key) in mapping.iter() { - if let Some(value) = tuple.get(*input_key) { - output_tuple.set(*output_key, value.clone()); - } - } - Ok(output_tuple) - })) + Box::new( + child(EncodedTuple::with_capacity(mapping.len())).filter_map( + move |tuple| { + match tuple { + Ok(tuple) => { + let mut output_tuple = from.clone(); + for (input_key, output_key) in mapping.iter() { + if let Some(value) = tuple.get(*input_key) { + if let Some(existing_value) = + output_tuple.get(*output_key) + { + if existing_value != value { + return None; // Conflict + } + } else { + output_tuple.set(*output_key, value.clone()); + } + } + } + Some(Ok(output_tuple)) + } + Err(e) => Some(Err(e)), + } + }, + ), + ) }) } PlanNode::Aggregate { diff --git a/testsuite/oxigraph-tests/sparql/manifest.ttl b/testsuite/oxigraph-tests/sparql/manifest.ttl index e215c315..621c63e9 100644 --- a/testsuite/oxigraph-tests/sparql/manifest.ttl +++ b/testsuite/oxigraph-tests/sparql/manifest.ttl @@ -27,6 +27,7 @@ :nested_expression :order_terms :nested_anonymous + :unbound_variable_in_subquery ) . :small_unicode_escape_with_multibytes_char rdf:type mf:NegativeSyntaxTest ; @@ -122,3 +123,9 @@ [ qt:query ; qt:data ] ; mf:result . + +:unbound_variable_in_subquery rdf:type mf:QueryEvaluationTest ; + mf:name "Variable should stay not bound in subqueries even if they are bound in the parent query" ; + mf:action + [ qt:query ] ; + mf:result . diff --git a/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.rq b/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.rq new file mode 100644 index 00000000..3669a898 --- /dev/null +++ b/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.rq @@ -0,0 +1,6 @@ +PREFIX ex: + +SELECT ?a ?b WHERE { + BIND(ex:a as ?a) + {SELECT ?b WHERE { BIND(ex:b as ?b) FILTER(!BOUND(?a))}} +} diff --git a/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.srx b/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.srx new file mode 100644 index 00000000..3ee6cb7d --- /dev/null +++ b/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.srx @@ -0,0 +1,17 @@ + + + + + + + + + + http://example.com/a + + + http://example.com/b + + + + \ No newline at end of file