Skip to content

Commit db12fd1

Browse files
committed
GH-5286 Generalize concepts for evaluation steps and condition
1 parent a8ae08b commit db12fd1

13 files changed

+409
-355
lines changed

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryValueEvaluationStep.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
package org.eclipse.rdf4j.query.algebra.evaluation;
1313

1414
import java.util.function.Function;
15+
import java.util.function.Predicate;
1516

1617
import org.eclipse.rdf4j.model.Value;
1718
import org.eclipse.rdf4j.query.BindingSet;
1819
import org.eclipse.rdf4j.query.QueryEvaluationException;
1920
import org.eclipse.rdf4j.query.algebra.ValueConstant;
2021
import org.eclipse.rdf4j.query.algebra.ValueExpr;
22+
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
2123

2224
/**
2325
* A step in the query evaluation that works on ValueExpresions.
@@ -26,6 +28,18 @@ public interface QueryValueEvaluationStep {
2628
Value evaluate(BindingSet bindings)
2729
throws QueryEvaluationException;
2830

31+
default Predicate<BindingSet> asPredicate() {
32+
return bs -> {
33+
try {
34+
Value value = evaluate(bs);
35+
return QueryEvaluationUtility.getEffectiveBooleanValue(value).orElse(false);
36+
} catch (ValueExprEvaluationException e) {
37+
// Ignore, condition not evaluated successfully
38+
return false;
39+
}
40+
};
41+
}
42+
2943
/**
3044
* If an value expression results in a constant then it may be executed once per query invocation. This can reduce
3145
* computation time significantly.

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/LeftJoinQueryEvaluationStep.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
2121
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
2222
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
23+
import org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps.values.ScopedQueryValueEvaluationStep;
2324
import org.eclipse.rdf4j.query.algebra.evaluation.iterator.*;
2425
import org.eclipse.rdf4j.query.algebra.helpers.TupleExprs;
2526
import org.eclipse.rdf4j.query.algebra.helpers.collectors.VarNameCollector;
@@ -125,13 +126,13 @@ public static QueryEvaluationStep determineRightEvaluationStep(
125126
if (joinCondition == null) {
126127
return prepareRightArg;
127128
} else if (canEvaluateConditionBasedOnLeftHandSide(join)) {
128-
return new LeftJoinPreFilterQueryEvaluationStep(
129+
return new PreFilterQueryEvaluationStep(
129130
prepareRightArg,
130-
new ScopeBindingsJoinConditionEvaluator(join.getAssuredBindingNames(), joinCondition));
131+
new ScopedQueryValueEvaluationStep(join.getAssuredBindingNames(), joinCondition));
131132
} else {
132-
return new LeftJoinPostFilterQueryEvaluationStep(
133+
return new PostFilterQueryEvaluationStep(
133134
prepareRightArg,
134-
new ScopeBindingsJoinConditionEvaluator(scopeBindingNames, joinCondition));
135+
new ScopedQueryValueEvaluationStep(scopeBindingNames, joinCondition));
135136
}
136137
}
137138

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Eclipse RDF4J contributors.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Distribution License v1.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/org/documents/edl-v10.php.
8+
*
9+
* SPDX-License-Identifier: BSD-3-Clause
10+
*******************************************************************************/
11+
package org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps;
12+
13+
import java.util.function.Predicate;
14+
15+
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
16+
import org.eclipse.rdf4j.common.iteration.FilterIteration;
17+
import org.eclipse.rdf4j.query.BindingSet;
18+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
19+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
20+
21+
public class PostFilterQueryEvaluationStep implements QueryEvaluationStep {
22+
23+
private final QueryEvaluationStep wrapped;
24+
private final Predicate<BindingSet> condition;
25+
26+
public PostFilterQueryEvaluationStep(QueryEvaluationStep wrapped,
27+
QueryValueEvaluationStep condition) {
28+
this.wrapped = wrapped;
29+
this.condition = condition.asPredicate();
30+
}
31+
32+
@Override
33+
public CloseableIteration<BindingSet> evaluate(BindingSet leftBindings) {
34+
var rightIteration = wrapped.evaluate(leftBindings);
35+
36+
if (rightIteration == QueryEvaluationStep.EMPTY_ITERATION) {
37+
return rightIteration;
38+
}
39+
40+
return new FilterIteration<>(rightIteration) {
41+
42+
@Override
43+
protected boolean accept(BindingSet bindings) {
44+
return condition.test(bindings);
45+
}
46+
47+
@Override
48+
protected void handleClose() {
49+
// Nothing to close
50+
}
51+
};
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Eclipse RDF4J contributors.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Distribution License v1.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/org/documents/edl-v10.php.
8+
*
9+
* SPDX-License-Identifier: BSD-3-Clause
10+
*******************************************************************************/
11+
package org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps;
12+
13+
import java.util.function.Predicate;
14+
15+
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
16+
import org.eclipse.rdf4j.query.BindingSet;
17+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
18+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
19+
20+
public class PreFilterQueryEvaluationStep implements QueryEvaluationStep {
21+
22+
private final QueryEvaluationStep wrapped;
23+
private final Predicate<BindingSet> condition;
24+
25+
public PreFilterQueryEvaluationStep(QueryEvaluationStep wrapped,
26+
QueryValueEvaluationStep condition) {
27+
this.wrapped = wrapped;
28+
this.condition = condition.asPredicate();
29+
}
30+
31+
@Override
32+
public CloseableIteration<BindingSet> evaluate(BindingSet leftBindings) {
33+
if (!condition.test(leftBindings)) {
34+
// Usage of this method assume this instance is returned
35+
return QueryEvaluationStep.EMPTY_ITERATION;
36+
}
37+
38+
return wrapped.evaluate(leftBindings);
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Eclipse RDF4J contributors.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Distribution License v1.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/org/documents/edl-v10.php.
8+
*
9+
* SPDX-License-Identifier: BSD-3-Clause
10+
*******************************************************************************/
11+
package org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps.values;
12+
13+
import java.util.Set;
14+
15+
import org.eclipse.rdf4j.model.Value;
16+
import org.eclipse.rdf4j.query.Binding;
17+
import org.eclipse.rdf4j.query.BindingSet;
18+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet;
19+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
20+
21+
public class ScopedQueryValueEvaluationStep implements QueryValueEvaluationStep {
22+
23+
/**
24+
* The set of binding names that are "in scope" for the filter. The filter must not include bindings that are (only)
25+
* included because of the depth-first evaluation strategy in the evaluation of the constraint.
26+
*/
27+
private final Set<String> scopeBindingNames;
28+
private final QueryValueEvaluationStep wrapped;
29+
30+
public ScopedQueryValueEvaluationStep(Set<String> scopeBindingNames, QueryValueEvaluationStep condition) {
31+
this.scopeBindingNames = scopeBindingNames;
32+
this.wrapped = condition;
33+
}
34+
35+
@Override
36+
public Value evaluate(BindingSet bindings) {
37+
BindingSet scopeBindings = createScopeBindings(scopeBindingNames, bindings);
38+
39+
return wrapped.evaluate(scopeBindings);
40+
}
41+
42+
private BindingSet createScopeBindings(Set<String> scopeBindingNames, BindingSet bindings) {
43+
QueryBindingSet scopeBindings = new QueryBindingSet(scopeBindingNames.size());
44+
for (String scopeBindingName : scopeBindingNames) {
45+
Binding binding = bindings.getBinding(scopeBindingName);
46+
if (binding != null) {
47+
scopeBindings.addBinding(binding);
48+
}
49+
}
50+
51+
return scopeBindings;
52+
}
53+
}

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
*******************************************************************************/
1111
package org.eclipse.rdf4j.query.algebra.evaluation.iterator;
1212

13+
import java.util.NoSuchElementException;
14+
1315
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
1416
import org.eclipse.rdf4j.common.iteration.LookAheadIteration;
1517
import org.eclipse.rdf4j.query.BindingSet;
@@ -18,8 +20,6 @@
1820
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy;
1921
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
2022

21-
import java.util.NoSuchElementException;
22-
2323
public class LeftJoinIterator extends LookAheadIteration<BindingSet> {
2424
/*-----------*
2525
* Variables *

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinPostFilterQueryEvaluationStep.java

Lines changed: 0 additions & 40 deletions
This file was deleted.

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinPreFilterQueryEvaluationStep.java

Lines changed: 0 additions & 30 deletions
This file was deleted.

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ScopeBindingsJoinConditionEvaluator.java

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)