Skip to content

Commit 7ad3ebf

Browse files
GH-4646 remove intermediate joins
1 parent 541d712 commit 7ad3ebf

2 files changed

Lines changed: 47 additions & 31 deletions

File tree

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

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

13+
import java.util.HashSet;
1314
import java.util.Queue;
1415
import java.util.Set;
1516

@@ -66,6 +67,8 @@ public class PathIteration extends LookAheadIteration<BindingSet, QueryEvaluatio
6667

6768
private static final String JOINVAR_PREFIX = "intermediate_join_";
6869

70+
private final Set<String> namedIntermediateJoins = new HashSet<>();
71+
6972
public PathIteration(EvaluationStrategy strategy, Scope scope, Var startVar,
7073
TupleExpr pathExpression, Var endVar, Var contextVar, long minLength, BindingSet bindings)
7174
throws QueryEvaluationException {
@@ -104,10 +107,10 @@ protected BindingSet getNextElement() throws QueryEvaluationException {
104107

105108
while (currentIter != null && currentIter.hasNext()) {
106109
BindingSet potentialNextElement = currentIter.next();
107-
MutableBindingSet nextElement;
110+
QueryBindingSet nextElement;
108111
// if it is not a compatible type of BindingSet
109112
if (potentialNextElement instanceof QueryBindingSet) {
110-
nextElement = (MutableBindingSet) potentialNextElement;
113+
nextElement = (QueryBindingSet) potentialNextElement;
111114
} else {
112115
nextElement = new QueryBindingSet(potentialNextElement);
113116
}
@@ -121,22 +124,10 @@ protected BindingSet getNextElement() throws QueryEvaluationException {
121124
}
122125
}
123126

124-
Value v1, v2;
125-
126-
if (startVarFixed && endVarFixed && currentLength > 2) {
127-
v1 = getVarValue(startVar, startVarFixed, nextElement);
128-
v2 = nextElement.getValue("END_" + JOINVAR_PREFIX + this.hashCode());
129-
} else if (startVarFixed && endVarFixed && currentLength == 2) {
130-
v1 = getVarValue(startVar, startVarFixed, nextElement);
131-
v2 = nextElement.getValue(JOINVAR_PREFIX + (currentLength - 1) + "_" + this.hashCode());
132-
} else {
133-
v1 = getVarValue(startVar, startVarFixed, nextElement);
134-
v2 = getVarValue(endVar, endVarFixed, nextElement);
135-
}
127+
ValuePair vp = valuePairFromStartAndEnd(nextElement);
136128

137-
if (!isCyclicPath(v1, v2)) {
129+
if (!isCyclicPath(vp)) {
138130

139-
ValuePair vp = new ValuePair(v1, v2);
140131
if (reportedValues.contains(vp)) {
141132
// new arbitrary-length path semantics: filter out
142133
// duplicates
@@ -151,38 +142,38 @@ protected BindingSet getNextElement() throws QueryEvaluationException {
151142

152143
if (startVarFixed && endVarFixed) {
153144
Value endValue = getVarValue(endVar, endVarFixed, nextElement);
154-
if (endValue.equals(v2)) {
145+
if (endValue.equals(vp.endValue)) {
155146
add(reportedValues, vp);
156-
if (!v1.equals(v2)) {
147+
if (!vp.startValue.equals(vp.endValue)) {
157148
addToQueue(valueQueue, vp);
158149
}
159150
if (!nextElement.hasBinding(startVar.getName())) {
160-
addBinding(nextElement, startVar.getName(), v1);
151+
addBinding(nextElement, startVar.getName(), vp.startValue);
161152
}
162153
if (!nextElement.hasBinding(endVar.getName())) {
163-
addBinding(nextElement, endVar.getName(), v2);
154+
addBinding(nextElement, endVar.getName(), vp.endValue);
164155
}
165-
return nextElement;
156+
return removeIntermediateJoinVars(nextElement);
166157
} else {
167158
if (add(unreportedValues, vp)) {
168-
if (!v1.equals(v2)) {
159+
if (!vp.startValue.equals(vp.endValue)) {
169160
addToQueue(valueQueue, vp);
170161
}
171162
}
172163
continue again;
173164
}
174165
} else {
175166
add(reportedValues, vp);
176-
if (!v1.equals(v2)) {
167+
if (!vp.startValue.equals(vp.endValue)) {
177168
addToQueue(valueQueue, vp);
178169
}
179170
if (!nextElement.hasBinding(startVar.getName())) {
180-
addBinding(nextElement, startVar.getName(), v1);
171+
addBinding(nextElement, startVar.getName(), vp.startValue);
181172
}
182173
if (!nextElement.hasBinding(endVar.getName())) {
183-
addBinding(nextElement, endVar.getName(), v2);
174+
addBinding(nextElement, endVar.getName(), vp.endValue);
184175
}
185-
return nextElement;
176+
return removeIntermediateJoinVars(nextElement);
186177
}
187178
} else {
188179
continue again;
@@ -198,6 +189,27 @@ protected BindingSet getNextElement() throws QueryEvaluationException {
198189
}
199190
}
200191

192+
private BindingSet removeIntermediateJoinVars(QueryBindingSet nextElement) {
193+
nextElement.removeAll(namedIntermediateJoins);
194+
return nextElement;
195+
}
196+
197+
private ValuePair valuePairFromStartAndEnd(MutableBindingSet nextElement) {
198+
Value v1, v2;
199+
200+
if (startVarFixed && endVarFixed && currentLength > 2) {
201+
v1 = getVarValue(startVar, startVarFixed, nextElement);
202+
v2 = nextElement.getValue("END_" + JOINVAR_PREFIX + this.hashCode());
203+
} else if (startVarFixed && endVarFixed && currentLength == 2) {
204+
v1 = getVarValue(startVar, startVarFixed, nextElement);
205+
v2 = nextElement.getValue(JOINVAR_PREFIX + (currentLength - 1) + "_" + this.hashCode());
206+
} else {
207+
v1 = getVarValue(startVar, startVarFixed, nextElement);
208+
v2 = getVarValue(endVar, endVarFixed, nextElement);
209+
}
210+
return new ValuePair(v1, v2);
211+
}
212+
201213
private void addBinding(MutableBindingSet bs, String name, Value value) {
202214
bs.addBinding(name, value);
203215
}
@@ -242,12 +254,12 @@ private Value getVarValue(Var var, boolean fixedValue, BindingSet bindingSet) {
242254
return v;
243255
}
244256

245-
private boolean isCyclicPath(Value v1, Value v2) {
257+
private boolean isCyclicPath(ValuePair vp) {
246258
if (currentLength <= 2) {
247259
return false;
248260
}
249261

250-
return reportedValues.contains(new ValuePair(v1, v2));
262+
return reportedValues.contains(vp);
251263

252264
}
253265

@@ -426,9 +438,12 @@ public void meet(Var var) {
426438

427439
}
428440

441+
private Var createAnonVar(String varName, Value v, boolean anonymous) {
442+
namedIntermediateJoins.add(varName);
443+
return new Var(varName, null, anonymous, false);
444+
}
445+
429446
public Var createAnonVar(String varName) {
430-
Var var = new Var(varName);
431-
var.setAnonymous(true);
432-
return var;
447+
return createAnonVar(varName, null, true);
433448
}
434449
}

core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIterationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ void assertExpected(BindingSet result, Value subClass, Value superClass) {
110110
assertEquals(subClass, result.getBinding("subClass").getValue());
111111
assertTrue(result.hasBinding("superClass"), "path zlp evaluation should binding for superClass var");
112112
assertEquals(superClass, result.getBinding("superClass").getValue());
113+
assertEquals(2, result.size());
113114
}
114115

115116
@Test

0 commit comments

Comments
 (0)