Skip to content

Commit 8d8cd08

Browse files
jasperiqJervenBolleman
authored andcommitted
GH-5286 Determine right hand side evaluation type for well designed queries statically
1 parent 4f1a470 commit 8d8cd08

7 files changed

Lines changed: 74 additions & 77 deletions

File tree

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +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.iterator.BadlyDesignedLeftJoinIterator;
24-
import org.eclipse.rdf4j.query.algebra.evaluation.iterator.HashJoinIteration;
25-
import org.eclipse.rdf4j.query.algebra.evaluation.iterator.LeftJoinIterator;
23+
import org.eclipse.rdf4j.query.algebra.evaluation.iterator.*;
2624
import org.eclipse.rdf4j.query.algebra.helpers.TupleExprs;
2725
import org.eclipse.rdf4j.query.algebra.helpers.collectors.VarNameCollector;
2826

@@ -32,6 +30,7 @@ public final class LeftJoinQueryEvaluationStep implements QueryEvaluationStep {
3230
private final QueryEvaluationStep left;
3331
private final LeftJoin leftJoin;
3432
private final Set<String> optionalVars;
33+
private final QueryEvaluationStep wellDesignedRightEvaluationStep;
3534

3635
public static QueryEvaluationStep supply(EvaluationStrategy strategy, LeftJoin leftJoin,
3736
QueryEvaluationContext context) {
@@ -85,7 +84,11 @@ public LeftJoinQueryEvaluationStep(QueryEvaluationStep right, QueryValueEvaluati
8584
}
8685

8786
this.optionalVars = optionalVars;
88-
87+
this.wellDesignedRightEvaluationStep = determineRightEvaluationStep(
88+
leftJoin,
89+
right,
90+
condition,
91+
leftJoin.getBindingNames());
8992
}
9093

9194
@Override
@@ -103,14 +106,37 @@ public CloseableIteration<BindingSet> evaluate(BindingSet bindings) {
103106
if (containsNone) {
104107
// left join is "well designed"
105108
leftJoin.setAlgorithm(LeftJoinIterator.class.getSimpleName());
106-
var rightEvaluationStep = LeftJoinIterator.determineRightEvaluationStep(leftJoin, right, condition, leftJoin.getBindingNames());
107-
return LeftJoinIterator.getInstance(left, bindings, rightEvaluationStep);
109+
return LeftJoinIterator.getInstance(left, bindings, wellDesignedRightEvaluationStep);
108110
} else {
109111
Set<String> problemVars = new HashSet<>(optionalVars);
110112
problemVars.retainAll(bindings.getBindingNames());
111113

112114
leftJoin.setAlgorithm(BadlyDesignedLeftJoinIterator.class.getSimpleName());
113-
return new BadlyDesignedLeftJoinIterator(left, right, condition, bindings, problemVars, leftJoin);
115+
var rightEvaluationStep = determineRightEvaluationStep(leftJoin, right, condition, problemVars);
116+
return new BadlyDesignedLeftJoinIterator(left, bindings, problemVars, rightEvaluationStep);
114117
}
115118
}
119+
120+
public static QueryEvaluationStep determineRightEvaluationStep(
121+
LeftJoin join,
122+
QueryEvaluationStep prepareRightArg,
123+
QueryValueEvaluationStep joinCondition,
124+
Set<String> scopeBindingNames) {
125+
if (joinCondition == null) {
126+
return prepareRightArg;
127+
} else if (canEvaluateConditionBasedOnLeftHandSide(join)) {
128+
return new LeftJoinPreFilterQueryEvaluationStep(
129+
prepareRightArg,
130+
new ScopeBindingsJoinConditionEvaluator(join.getAssuredBindingNames(), joinCondition));
131+
} else {
132+
return new LeftJoinPostFilterQueryEvaluationStep(
133+
prepareRightArg,
134+
new ScopeBindingsJoinConditionEvaluator(scopeBindingNames, joinCondition));
135+
}
136+
}
137+
138+
private static boolean canEvaluateConditionBasedOnLeftHandSide(LeftJoin leftJoin) {
139+
var varNames = VarNameCollector.process(leftJoin.getCondition());
140+
return leftJoin.getAssuredBindingNames().containsAll(varNames);
141+
}
116142
}

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ public class BadlyDesignedLeftJoinIterator extends LeftJoinIterator {
4040
* Constructors *
4141
*--------------*/
4242

43-
public BadlyDesignedLeftJoinIterator(EvaluationStrategy strategy, LeftJoin join, BindingSet inputBindings,
44-
Set<String> problemVars, QueryEvaluationContext context) throws QueryEvaluationException {
45-
super(strategy, join, getFilteredBindings(inputBindings, problemVars), context);
43+
public BadlyDesignedLeftJoinIterator(
44+
EvaluationStrategy strategy,
45+
LeftJoin join,
46+
BindingSet inputBindings,
47+
Set<String> problemVars,
48+
QueryEvaluationStep rightEvaluationStep) throws QueryEvaluationException {
49+
super(strategy, join, getFilteredBindings(inputBindings, problemVars), rightEvaluationStep);
4650
this.inputBindings = inputBindings;
4751
this.problemVars = problemVars;
4852

@@ -53,13 +57,11 @@ public BadlyDesignedLeftJoinIterator(EvaluationStrategy strategy, LeftJoin join,
5357
*---------*/
5458

5559
public BadlyDesignedLeftJoinIterator(QueryEvaluationStep left,
56-
QueryEvaluationStep right,
57-
QueryValueEvaluationStep joinCondition,
5860
BindingSet inputBindings,
5961
Set<String> problemVars,
60-
LeftJoin leftJoin)
62+
QueryEvaluationStep rightEvaluationStep)
6163
throws QueryEvaluationException {
62-
super(left, right, joinCondition, getFilteredBindings(inputBindings, problemVars), problemVars, leftJoin);
64+
super(left, getFilteredBindings(inputBindings, problemVars), rightEvaluationStep);
6365
this.inputBindings = inputBindings;
6466
this.problemVars = problemVars;
6567
}

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

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@
1515
import org.eclipse.rdf4j.query.BindingSet;
1616
import org.eclipse.rdf4j.query.QueryEvaluationException;
1717
import org.eclipse.rdf4j.query.algebra.LeftJoin;
18-
import org.eclipse.rdf4j.query.algebra.evaluation.*;
19-
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
20-
import org.eclipse.rdf4j.query.algebra.helpers.collectors.VarNameCollector;
18+
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy;
19+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
2120

2221
import java.util.NoSuchElementException;
23-
import java.util.Optional;
24-
import java.util.Set;
2522

2623
public class LeftJoinIterator extends LookAheadIteration<BindingSet> {
2724
/*-----------*
@@ -41,35 +38,21 @@ public LeftJoinIterator(
4138
EvaluationStrategy strategy,
4239
LeftJoin join,
4340
BindingSet bindings,
44-
QueryEvaluationContext context) throws QueryEvaluationException {
45-
Set<String> scopeBindingNames = join.getBindingNames();
46-
41+
QueryEvaluationStep rightEvaluationStep) throws QueryEvaluationException {
4742
leftIter = strategy.evaluate(join.getLeftArg(), bindings);
4843

4944
rightIter = null;
5045

51-
QueryEvaluationStep prepareRightArg = strategy.precompile(join.getRightArg(), context);
5246
join.setAlgorithm(this);
53-
var joinCondition = Optional.ofNullable(join.getCondition())
54-
.map(condition -> strategy.precompile(condition, context));
55-
56-
rightEvaluationStep = determineRightEvaluationStep(
57-
join,
58-
prepareRightArg,
59-
joinCondition.orElse(null),
60-
scopeBindingNames);
47+
48+
this.rightEvaluationStep = rightEvaluationStep;
6149
}
6250

6351
public LeftJoinIterator(
6452
QueryEvaluationStep left,
65-
QueryEvaluationStep right,
66-
QueryValueEvaluationStep joinCondition,
6753
BindingSet bindings,
68-
Set<String> scopeBindingNames,
69-
LeftJoin leftJoin) throws QueryEvaluationException {
70-
this(
71-
left.evaluate(bindings),
72-
determineRightEvaluationStep(leftJoin, right, joinCondition, scopeBindingNames));
54+
QueryEvaluationStep rightEvaluationStep) throws QueryEvaluationException {
55+
this(left.evaluate(bindings), rightEvaluationStep);
7356
}
7457

7558
public LeftJoinIterator(CloseableIteration<BindingSet> leftIter, QueryEvaluationStep rightEvaluationStep) {
@@ -153,31 +136,4 @@ protected void handleClose() throws QueryEvaluationException {
153136
}
154137
}
155138
}
156-
157-
public static QueryEvaluationStep determineRightEvaluationStep(
158-
LeftJoin join,
159-
QueryEvaluationStep prepareRightArg,
160-
QueryValueEvaluationStep joinCondition,
161-
Set<String> scopeBindingNames) {
162-
if (joinCondition == null) {
163-
return prepareRightArg;
164-
} else if (canEvaluateConditionBasedOnLeftHandSide(join)) {
165-
return new LeftJoinPreFilterQueryEvaluationStep(
166-
prepareRightArg,
167-
new ScopeBindingsJoinConditionEvaluator(join.getAssuredBindingNames(), joinCondition));
168-
} else {
169-
return new LeftJoinPostFilterQueryEvaluationStep(
170-
prepareRightArg,
171-
new ScopeBindingsJoinConditionEvaluator(scopeBindingNames, joinCondition));
172-
}
173-
}
174-
175-
private static boolean canEvaluateConditionBasedOnLeftHandSide(LeftJoin leftJoin) {
176-
if (!leftJoin.hasCondition()) {
177-
return false;
178-
}
179-
180-
var varNames = VarNameCollector.process(leftJoin.getCondition());
181-
return leftJoin.getAssuredBindingNames().containsAll(varNames);
182-
}
183139
}

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
import org.eclipse.rdf4j.query.BindingSet;
66
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
77

8-
class LeftJoinPostFilterQueryEvaluationStep implements QueryEvaluationStep {
8+
public class LeftJoinPostFilterQueryEvaluationStep implements QueryEvaluationStep {
99

1010
private final QueryEvaluationStep wrapped;
1111
private final ScopeBindingsJoinConditionEvaluator joinConditionEvaluator;
1212

13-
LeftJoinPostFilterQueryEvaluationStep(
14-
QueryEvaluationStep wrapped,
15-
ScopeBindingsJoinConditionEvaluator joinConditionEvaluator) {
13+
public LeftJoinPostFilterQueryEvaluationStep(QueryEvaluationStep wrapped,
14+
ScopeBindingsJoinConditionEvaluator joinConditionEvaluator) {
1615
this.wrapped = wrapped;
1716
this.joinConditionEvaluator = joinConditionEvaluator;
1817
}

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44
import org.eclipse.rdf4j.query.BindingSet;
55
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
66

7-
class LeftJoinPreFilterQueryEvaluationStep implements QueryEvaluationStep {
7+
public class LeftJoinPreFilterQueryEvaluationStep implements QueryEvaluationStep {
88

99
private final QueryEvaluationStep wrapped;
1010
private final ScopeBindingsJoinConditionEvaluator joinConditionEvaluator;
1111

12-
LeftJoinPreFilterQueryEvaluationStep(
13-
QueryEvaluationStep wrapped,
14-
ScopeBindingsJoinConditionEvaluator joinConditionEvaluator) {
12+
public LeftJoinPreFilterQueryEvaluationStep(QueryEvaluationStep wrapped,
13+
ScopeBindingsJoinConditionEvaluator joinConditionEvaluator) {
1514
this.wrapped = wrapped;
1615
this.joinConditionEvaluator = joinConditionEvaluator;
1716
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import java.util.Set;
1212

13-
class ScopeBindingsJoinConditionEvaluator {
13+
public class ScopeBindingsJoinConditionEvaluator {
1414

1515
/**
1616
* The set of binding names that are "in scope" for the filter. The filter must not include bindings that are (only)
@@ -19,7 +19,7 @@ class ScopeBindingsJoinConditionEvaluator {
1919
private final Set<String> scopeBindingNames;
2020
private final QueryValueEvaluationStep joinCondition;
2121

22-
ScopeBindingsJoinConditionEvaluator(Set<String> scopeBindingNames, QueryValueEvaluationStep joinCondition) {
22+
public ScopeBindingsJoinConditionEvaluator(Set<String> scopeBindingNames, QueryValueEvaluationStep joinCondition) {
2323
this.scopeBindingNames = scopeBindingNames;
2424
this.joinCondition = joinCondition;
2525
}

tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/FederationEvalStrategy.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import java.util.HashSet;
1414
import java.util.List;
15+
import java.util.Optional;
1516
import java.util.Set;
1617
import java.util.concurrent.Executor;
1718
import java.util.concurrent.atomic.AtomicBoolean;
@@ -116,6 +117,7 @@
116117
import org.eclipse.rdf4j.query.algebra.evaluation.impl.EvaluationStatistics;
117118
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
118119
import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy;
120+
import org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps.LeftJoinQueryEvaluationStep;
119121
import org.eclipse.rdf4j.query.algebra.evaluation.iterator.BadlyDesignedLeftJoinIterator;
120122
import org.eclipse.rdf4j.query.algebra.evaluation.iterator.HashJoinIteration;
121123
import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ConstantOptimizer;
@@ -813,8 +815,21 @@ public CloseableIteration<BindingSet> evaluate(BindingSet bindings) {
813815
} else {
814816
Set<String> problemVarsClone = new HashSet<>(problemVars);
815817
problemVarsClone.retainAll(bindings.getBindingNames());
816-
return new BadlyDesignedLeftJoinIterator(FederationEvalStrategy.this, leftJoin, bindings,
817-
problemVarsClone, context);
818+
QueryEvaluationStep preCompiledRight = this.precompile(leftJoin.getRightArg(), context);
819+
var joinCondition = Optional.ofNullable(leftJoin.getCondition())
820+
.map(condition -> this.precompile(condition, context))
821+
.orElse(null);
822+
var rightEvaluationStep = LeftJoinQueryEvaluationStep.determineRightEvaluationStep(
823+
leftJoin,
824+
preCompiledRight,
825+
joinCondition,
826+
problemVars);
827+
return new BadlyDesignedLeftJoinIterator(
828+
FederationEvalStrategy.this,
829+
leftJoin,
830+
bindings,
831+
problemVarsClone,
832+
rightEvaluationStep);
818833
}
819834
};
820835
}

0 commit comments

Comments
 (0)