From 4cc9e4008b77fe120e5bbc8494e5e6fcf03c052a Mon Sep 17 00:00:00 2001 From: Tpt Date: Wed, 31 May 2023 20:34:16 +0200 Subject: [PATCH] Fixes empty IN expression optimization --- lib/src/sparql/plan_builder.rs | 39 ++++++++++++------- .../oxigraph-tests/sparql/in_empty_error.rq | 1 + .../oxigraph-tests/sparql/in_empty_error.srx | 9 +++++ testsuite/oxigraph-tests/sparql/manifest.ttl | 6 +++ 4 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 testsuite/oxigraph-tests/sparql/in_empty_error.rq create mode 100644 testsuite/oxigraph-tests/sparql/in_empty_error.srx diff --git a/lib/src/sparql/plan_builder.rs b/lib/src/sparql/plan_builder.rs index 657d6f91..6592d56c 100644 --- a/lib/src/sparql/plan_builder.rs +++ b/lib/src/sparql/plan_builder.rs @@ -432,23 +432,32 @@ impl<'a> PlanBuilder<'a> { Box::new(self.build_for_expression(b, variables, graph_name)?), ), Expression::In(e, l) => { + let e = self.build_for_expression(e, variables, graph_name)?; if l.is_empty() { - return Ok(PlanExpression::Literal(PlanTerm { - encoded: false.into(), - plain: false.into(), - })); + // False except on error + PlanExpression::If( + Box::new(e), + Box::new(PlanExpression::Literal(PlanTerm { + encoded: false.into(), + plain: false.into(), + })), + Box::new(PlanExpression::Literal(PlanTerm { + encoded: false.into(), + plain: false.into(), + })), + ) + } else { + PlanExpression::Or( + l.iter() + .map(|v| { + Ok(PlanExpression::Equal( + Box::new(e.clone()), + Box::new(self.build_for_expression(v, variables, graph_name)?), + )) + }) + .collect::>()?, + ) } - let e = self.build_for_expression(e, variables, graph_name)?; - PlanExpression::Or( - l.iter() - .map(|v| { - Ok(PlanExpression::Equal( - Box::new(e.clone()), - Box::new(self.build_for_expression(v, variables, graph_name)?), - )) - }) - .collect::>()?, - ) } Expression::Add(a, b) => PlanExpression::Add( Box::new(self.build_for_expression(a, variables, graph_name)?), diff --git a/testsuite/oxigraph-tests/sparql/in_empty_error.rq b/testsuite/oxigraph-tests/sparql/in_empty_error.rq new file mode 100644 index 00000000..96060b9f --- /dev/null +++ b/testsuite/oxigraph-tests/sparql/in_empty_error.rq @@ -0,0 +1 @@ +SELECT ?r WHERE { BIND((?foo IN ()) AS ?r) } \ No newline at end of file diff --git a/testsuite/oxigraph-tests/sparql/in_empty_error.srx b/testsuite/oxigraph-tests/sparql/in_empty_error.srx new file mode 100644 index 00000000..762d6c88 --- /dev/null +++ b/testsuite/oxigraph-tests/sparql/in_empty_error.srx @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/testsuite/oxigraph-tests/sparql/manifest.ttl b/testsuite/oxigraph-tests/sparql/manifest.ttl index 92684953..21ef9e76 100644 --- a/testsuite/oxigraph-tests/sparql/manifest.ttl +++ b/testsuite/oxigraph-tests/sparql/manifest.ttl @@ -30,6 +30,7 @@ :unbound_variable_in_subquery :one_or_more_shared :one_or_more_star + :in_empty_error ) . :small_unicode_escape_with_multibytes_char rdf:type mf:NegativeSyntaxTest ; @@ -140,3 +141,8 @@ [ qt:query ; qt:data ] ; mf:result . + +:in_empty_error rdf:type mf:QueryEvaluationTest ; + mf:name "IN should propagate errors on the left side, even on the empty input" ; + mf:action [ qt:query ] ; + mf:result .