Skip to content

Commit db527a8

Browse files
committed
Try to ensure that all expressions within a builder evaluate to an RDF term
1 parent 414d896 commit db527a8

File tree

10 files changed

+219
-210
lines changed

10 files changed

+219
-210
lines changed

lib/engine/src/sparql/rewriting/expression_rewriter.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
use crate::sparql::rewriting::GraphPatternRewriter;
22
use crate::DFResult;
3-
use datafusion::arrow::datatypes::DataType;
43
use datafusion::common::{internal_err, plan_datafusion_err, plan_err, Column, Spans};
54
use datafusion::functions_aggregate::count::count;
65
use datafusion::logical_expr::utils::COUNT_STAR_EXPANSION;
76
use datafusion::logical_expr::{
8-
lit, or, Expr, ExprSchemable, LogicalPlanBuilder, Operator, Subquery,
7+
lit, or, Expr, LogicalPlanBuilder, Operator, Subquery,
98
};
109
use datafusion::prelude::{and, exists};
11-
use rdf_fusion_encoding::EncodingName;
1210
use rdf_fusion_logical::{RdfFusionExprBuilder, RdfFusionExprBuilderRoot};
1311
use rdf_fusion_model::vocab::xsd;
1412
use rdf_fusion_model::Iri;
@@ -45,12 +43,8 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
4543

4644
/// Rewrites an [Expression] to an [Expr] that computes a native Boolean.
4745
pub fn rewrite_to_boolean(&self, expression: &Expression) -> DFResult<Expr> {
48-
let expr = self.rewrite_internal(expression)?;
49-
if expr.evaluates_to_boolean()? {
50-
return expr.build();
51-
}
52-
53-
expr.build_effective_boolean_value()?.build_boolean()
46+
self.rewrite_internal(expression)?
47+
.build_effective_boolean_value()
5448
}
5549

5650
fn rewrite_internal(
@@ -66,7 +60,10 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
6660
.rewrite_internal(lhs)?
6761
.rdf_term_equal(self.rewrite(rhs)?),
6862
Expression::SameTerm(lhs, rhs) => {
69-
self.rewrite_internal(lhs)?.build_same_term(self.rewrite(rhs)?)
63+
let boolean = self
64+
.rewrite_internal(lhs)?
65+
.build_same_term(self.rewrite(rhs)?)?;
66+
self.expr_builder_root.native_boolean_as_term(boolean)
7067
}
7168
Expression::Greater(lhs, rhs) => {
7269
self.rewrite_internal(lhs)?.greater_than(self.rewrite(rhs)?)
@@ -297,13 +294,12 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
297294
.map(|e| {
298295
lhs.clone()
299296
.rdf_term_equal(self.rewrite(e)?)?
300-
.build_effective_boolean_value()?
301-
.build_boolean()
297+
.build_effective_boolean_value()
302298
})
303299
.collect::<DFResult<Vec<_>>>()?;
304300

305301
let result = expressions.into_iter().reduce(or).unwrap_or(lit(false));
306-
self.expr_builder(result).native_boolean_as_term()
302+
self.expr_builder_root.native_boolean_as_term(result)
307303
}
308304

309305
/// Rewrites an EXISTS expression to a correlated subquery.
@@ -335,9 +331,10 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
335331
outer_ref_columns: vec![],
336332
spans: Spans(vec![]),
337333
};
334+
338335
return self
339-
.expr_builder(Expr::ScalarSubquery(subquery).gt(lit(0)))
340-
.native_boolean_as_term();
336+
.expr_builder_root
337+
.native_boolean_as_term(Expr::ScalarSubquery(subquery).gt(lit(0)));
341338
}
342339

343340
// TODO: Investigate why we need this renaming and cannot refer to the unqualified column
@@ -365,9 +362,10 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
365362
.try_create_builder(Expr::OuterReferenceColumn(
366363
data_type.clone(),
367364
Column::new_unqualified(k),
368-
))
369-
.is_compatible(Expr::from(Column::new_unqualified(format!("__inner__{k}"))))?
370-
.build_boolean()
365+
))?
366+
.build_is_compatible(Expr::from(Column::new_unqualified(format!(
367+
"__inner__{k}"
368+
))))
371369
})
372370
.collect::<DFResult<Vec<_>>>()?;
373371
let compatible_filter = compatible_filters
@@ -376,7 +374,8 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
376374
.unwrap_or(lit(true));
377375

378376
let subquery = Arc::new(exists_pattern.filter(compatible_filter)?.build()?);
379-
self.expr_builder(exists(subquery)).native_boolean_as_term()
377+
self.expr_builder_root
378+
.native_boolean_as_term(exists(subquery))
380379
}
381380

382381
/// Rewrites an IF expression to a case expression.
@@ -398,29 +397,30 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
398397
lhs: &Expression,
399398
rhs: &Expression,
400399
) -> DFResult<RdfFusionExprBuilder<'rewriter>> {
401-
let lhs = self.rewrite_internal(lhs)?.build_effective_boolean_value()?;
400+
let lhs = self
401+
.rewrite_internal(lhs)?
402+
.build_effective_boolean_value()?;
402403
let rhs = self
403404
.rewrite_internal(rhs)?
404-
.build_effective_boolean_value()?
405-
.build_boolean()?;
405+
.build_effective_boolean_value()?;
406406

407407
let result = match operator {
408-
Operator::And => lhs.and(rhs)?,
409-
Operator::Or => lhs.or(rhs)?,
408+
Operator::And => self.expr_builder_root.sparql_and(lhs, rhs)?,
409+
Operator::Or => self.expr_builder_root.sparql_or(lhs, rhs)?,
410410
_ => return plan_err!("Unsupported logical expression: {}", &operator),
411411
};
412-
result.native_boolean_as_term()
412+
self.expr_builder_root.native_boolean_as_term(result)
413413
}
414414

415415
/// TODO
416-
fn expr_builder(&self, expr: Expr) -> RdfFusionExprBuilder<'rewriter> {
416+
fn expr_builder(&self, expr: Expr) -> DFResult<RdfFusionExprBuilder<'rewriter>> {
417417
self.expr_builder_root.try_create_builder(expr)
418418
}
419419

420420
/// TODO
421421
fn unary_args(&self, args: Vec<Expr>) -> DFResult<RdfFusionExprBuilder<'rewriter>> {
422422
match TryInto::<[Expr; 1]>::try_into(args) {
423-
Ok([expr]) => Ok(self.expr_builder(expr)),
423+
Ok([expr]) => Ok(self.expr_builder(expr)?),
424424
Err(_) => plan_err!("Unsupported argument list for unary function."),
425425
}
426426
}
@@ -429,7 +429,7 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
429429
fn binary_args(&self, args: Vec<Expr>) -> DFResult<(RdfFusionExprBuilder<'rewriter>, Expr)> {
430430
match TryInto::<[Expr; 2]>::try_into(args) {
431431
Ok([lhs, rhs]) => {
432-
let lhs = self.expr_builder(lhs);
432+
let lhs = self.expr_builder(lhs)?;
433433
Ok((lhs, rhs))
434434
}
435435
Err(_) => plan_err!("Unsupported argument list for unary function."),
@@ -443,7 +443,7 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
443443
) -> DFResult<(RdfFusionExprBuilder<'rewriter>, Expr, Expr)> {
444444
match TryInto::<[Expr; 3]>::try_into(args) {
445445
Ok([arg0, arg1, arg2]) => {
446-
let arg0 = self.expr_builder(arg0);
446+
let arg0 = self.expr_builder(arg0)?;
447447
Ok((arg0, arg1, arg2))
448448
}
449449
Err(_) => plan_err!("Unsupported argument list for unary function."),
@@ -457,7 +457,7 @@ impl<'rewriter> ExpressionRewriter<'rewriter> {
457457
) -> DFResult<(RdfFusionExprBuilder<'rewriter>, Expr, Expr, Expr)> {
458458
match TryInto::<[Expr; 4]>::try_into(args) {
459459
Ok([arg0, arg1, arg2, arg3]) => {
460-
let arg0 = self.expr_builder(arg0);
460+
let arg0 = self.expr_builder(arg0)?;
461461
Ok((arg0, arg1, arg2, arg3))
462462
}
463463
Err(_) => plan_err!("Unsupported argument list for unary function."),

lib/engine/src/sparql/rewriting/graph_pattern_rewriter.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use datafusion::arrow::datatypes::DataType;
55
use datafusion::common::{not_impl_err, plan_err, Column, DFSchema};
66
use datafusion::functions_aggregate::count::{count, count_udaf};
77
use datafusion::logical_expr::utils::COUNT_STAR_EXPANSION;
8-
use datafusion::logical_expr::{Expr, ExprSchemable, LogicalPlan, SortExpr};
8+
use datafusion::logical_expr::{Expr, LogicalPlan, SortExpr};
99
use rdf_fusion_encoding::EncodingName;
1010
use rdf_fusion_functions::registry::{RdfFusionFunctionRegistry, RdfFusionFunctionRegistryRef};
1111
use rdf_fusion_logical::join::SparqlJoinType;
@@ -272,7 +272,7 @@ impl GraphPatternRewriter {
272272
OrderExpression::Desc(inner) => (false, expression_rewriter.rewrite(inner)?),
273273
};
274274
Ok(expr_builder_root
275-
.try_create_builder(expression)
275+
.try_create_builder(expression)?
276276
.with_encoding(EncodingName::Sortable)?
277277
.build()?
278278
.sort(asc, true))
@@ -315,7 +315,7 @@ impl GraphPatternRewriter {
315315
} => {
316316
let expr = expression_rewriter.rewrite(expr)?;
317317
let expr = expr_builder_root
318-
.try_create_builder(expr)
318+
.try_create_builder(expr)?
319319
.with_encoding(EncodingName::TypedValue)?;
320320
Ok(match name {
321321
AggregateFunction::Avg => expr.avg(*distinct),
@@ -423,9 +423,12 @@ fn ensure_all_columns_are_rdf_terms(
423423
) {
424424
Ok(column)
425425
} else {
426-
let expr_builder = inner.expr_builder(column);
427426
match f.data_type() {
428-
DataType::Int64 => Ok(expr_builder.native_int64_as_term()?.alias(f.name())),
427+
DataType::Int64 => Ok(inner
428+
.expr_builder_root()
429+
.native_int64_as_term(column)?
430+
.build()?
431+
.alias(f.name())),
429432
other => plan_err!("Unsupported data type {:?}", other),
430433
}
431434
}

0 commit comments

Comments
 (0)