Skip to content

Commit 1a77ac1

Browse files
committed
Merge branch 'temp-main-to-merge' into merge-main-7
# Conflicts: # core/collection-factory/mapdb3/pom.xml # core/common/order/pom.xml # core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ArrayBindingSet.java # core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ArrayBindingBasedQueryEvaluationContext.java # core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/DefaultEvaluationStrategy.java # core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/FilterIterator.java # core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java # testsuites/shacl/pom.xml # testsuites/sparql/src/main/java/org/eclipse/rdf4j/testsuite/sparql/RepositorySPARQLComplianceTestSuite.java
2 parents 0ef1d99 + f0d2f52 commit 1a77ac1

33 files changed

Lines changed: 999 additions & 297 deletions

File tree

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

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
*******************************************************************************/
1111
package org.eclipse.rdf4j.query.algebra.evaluation;
1212

13+
import java.util.AbstractSet;
1314
import java.util.ArrayList;
1415
import java.util.Arrays;
16+
import java.util.Collection;
1517
import java.util.Collections;
18+
import java.util.ConcurrentModificationException;
1619
import java.util.Iterator;
17-
import java.util.LinkedHashSet;
1820
import java.util.List;
21+
import java.util.NoSuchElementException;
1922
import java.util.Set;
2023
import java.util.function.BiConsumer;
2124
import java.util.function.Function;
@@ -182,30 +185,21 @@ private int getIndex(String bindingName) {
182185

183186
@Override
184187
public Set<String> getBindingNames() {
185-
if (bindingNamesSetCache == null) {
186-
int size = size();
187-
if (size == 0) {
188-
this.bindingNamesSetCache = Collections.emptySet();
189-
} else if (size == 1) {
190-
for (int i = 0; i < this.bindingNames.length; i++) {
191-
if (whichBindingsHaveBeenSet[i]) {
192-
this.bindingNamesSetCache = Collections.singleton(bindingNames[i]);
193-
break;
194-
}
188+
final int size = ArrayBindingSet.this.size();
189+
switch (size) {
190+
case 0:
191+
return Collections.emptySet();
192+
case 1:
193+
for (int i = 0; i < this.bindingNames.length; i++) {
194+
if (whichBindingsHaveBeenSet[i]) {
195+
return Collections.singleton(bindingNames[i]);
195196
}
196-
assert this.bindingNamesSetCache != null;
197-
} else {
198-
LinkedHashSet<String> bindingNamesSetCache = new LinkedHashSet<>(size * 2);
199-
for (int i = 0; i < this.bindingNames.length; i++) {
200-
if (whichBindingsHaveBeenSet[i]) {
201-
bindingNamesSetCache.add(bindingNames[i]);
202-
}
203-
}
204-
this.bindingNamesSetCache = Collections.unmodifiableSet(bindingNamesSetCache);
205197
}
198+
throw new ConcurrentModificationException(
199+
"An bindingset has been modified during the getBindingNames call");
200+
default:
201+
return new MinimallyAllocatingSet(size);
206202
}
207-
208-
return bindingNamesSetCache;
209203
}
210204

211205
@Override
@@ -295,6 +289,53 @@ public List<String> getSortedBindingNames() {
295289
/*------------------------------------*
296290
* Inner class ArrayBindingSetIterator *
297291
*------------------------------------*/
292+
private static final class BindingToBindingNameIterator implements Iterator<String> {
293+
private final Iterator<Binding> nested;
294+
295+
private BindingToBindingNameIterator(Iterator<Binding> nested) {
296+
this.nested = nested;
297+
}
298+
299+
@Override
300+
public boolean hasNext() {
301+
return nested.hasNext();
302+
}
303+
304+
@Override
305+
public String next() {
306+
return nested.next().getName();
307+
}
308+
}
309+
310+
private final class MinimallyAllocatingSet extends AbstractSet<String> {
311+
312+
private final int size;
313+
314+
private MinimallyAllocatingSet(int size) {
315+
this.size = size;
316+
}
317+
318+
@Override
319+
public int size() {
320+
return size;
321+
}
322+
323+
@Override
324+
public Iterator<String> iterator() {
325+
Iterator<Binding> nested = ArrayBindingSet.this.iterator();
326+
return new BindingToBindingNameIterator(nested);
327+
}
328+
329+
@Override
330+
public boolean add(String e) {
331+
throw new UnsupportedOperationException();
332+
}
333+
334+
@Override
335+
public boolean addAll(Collection<? extends String> c) {
336+
throw new UnsupportedOperationException();
337+
}
338+
}
298339

299340
private class ArrayBindingSetIterator implements Iterator<Binding> {
300341

@@ -305,6 +346,7 @@ public ArrayBindingSetIterator() {
305346

306347
@Override
307348
public boolean hasNext() {
349+
// If the current index is at at a set value then this wont advance again.
308350
for (; index < values.length; index++) {
309351
if (whichBindingsHaveBeenSet[index] && values[index] != null) {
310352
return true;
@@ -321,12 +363,16 @@ public Binding next() {
321363
}
322364
}
323365

324-
String name = bindingNames[index];
325-
Value value = values[index++];
326-
if (value != null) {
327-
return new SimpleBinding(name, value);
328-
} else {
329-
return null;
366+
try {
367+
String name = bindingNames[index];
368+
Value value = values[index++];
369+
if (value != null) {
370+
return new SimpleBinding(name, value);
371+
} else {
372+
return null;
373+
}
374+
} catch (ArrayIndexOutOfBoundsException e) {
375+
throw new NoSuchElementException();
330376
}
331377
}
332378

@@ -347,11 +393,9 @@ public void addBinding(Binding binding) {
347393
return;
348394
}
349395

350-
assert !this.whichBindingsHaveBeenSet[index];
396+
assert !this.whichBindingsHaveBeenSet[index] : "variable already bound: " + binding.getName();
351397
this.values[index] = binding.getValue();
352398
this.whichBindingsHaveBeenSet[index] = true;
353-
clearCache();
354-
355399
}
356400

357401
@Override
@@ -362,7 +406,6 @@ public void setBinding(Binding binding) {
362406
}
363407
this.values[index] = binding.getValue();
364408
this.whichBindingsHaveBeenSet[index] = true;
365-
clearCache();
366409
}
367410

368411
@Override

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

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public final class ArrayBindingBasedQueryEvaluationContext implements QueryEvalu
5757
private final BiConsumer<Value, MutableBindingSet>[] addBinding;
5858
private final Comparator<Value> comparator;
5959

60-
boolean initialized;
60+
private final boolean initialized;
6161

6262
ArrayBindingBasedQueryEvaluationContext(QueryEvaluationContext context, String[] allVariables,
6363
Comparator<Value> comparator) {
@@ -118,7 +118,12 @@ public Predicate<BindingSet> hasBinding(String variableName) {
118118

119119
assert variableName != null && !variableName.isEmpty();
120120
Function<ArrayBindingSet, Boolean> directHasVariable = defaultArrayBindingSet.getDirectHasBinding(variableName);
121-
return new HasBinding(variableName, directHasVariable);
121+
if (directHasVariable != null) {
122+
return new HasBinding(variableName, directHasVariable);
123+
} else {
124+
// If the variable is not in the default set, it can never be part of this array binding
125+
return (bs) -> false;
126+
}
122127
}
123128

124129
static private class HasBinding implements Predicate<BindingSet> {
@@ -156,16 +161,19 @@ public Function<BindingSet, Binding> getBinding(String variableName) {
156161

157162
Function<ArrayBindingSet, Binding> directAccessForVariable = defaultArrayBindingSet
158163
.getDirectGetBinding(variableName);
159-
return bs -> {
160-
if (bs.isEmpty()) {
161-
return null;
162-
}
163-
if (bs instanceof ArrayBindingSet) {
164-
return directAccessForVariable.apply((ArrayBindingSet) bs);
165-
} else {
166-
return bs.getBinding(variableName);
167-
}
168-
};
164+
if (directAccessForVariable != null) {
165+
return (bs) -> {
166+
if (bs.isEmpty()) {
167+
return null;
168+
} else if (bs instanceof ArrayBindingSet) {
169+
return directAccessForVariable.apply((ArrayBindingSet) bs);
170+
} else {
171+
return bs.getBinding(variableName);
172+
}
173+
};
174+
} else {
175+
return (bs) -> null;
176+
}
169177
}
170178

171179
@Override
@@ -180,7 +188,12 @@ public Function<BindingSet, Value> getValue(String variableName) {
180188

181189
Function<ArrayBindingSet, Value> directAccessForVariable = defaultArrayBindingSet
182190
.getDirectGetValue(variableName);
183-
return new ValueGetter(variableName, directAccessForVariable);
191+
if (directAccessForVariable != null) {
192+
return new ValueGetter(variableName, directAccessForVariable);
193+
} else {
194+
// If the variable is not in the default set, it can never be part of this array binding
195+
return (bs) -> null;
196+
}
184197
}
185198

186199
private static class ValueGetter implements Function<BindingSet, Value> {
@@ -219,13 +232,17 @@ public BiConsumer<Value, MutableBindingSet> setBinding(String variableName) {
219232

220233
BiConsumer<Value, ArrayBindingSet> directAccessForVariable = defaultArrayBindingSet
221234
.getDirectSetBinding(variableName);
222-
return (val, bs) -> {
223-
if (bs instanceof ArrayBindingSet) {
224-
directAccessForVariable.accept(val, (ArrayBindingSet) bs);
225-
} else {
226-
bs.setBinding(variableName, val);
227-
}
228-
};
235+
if (directAccessForVariable != null) {
236+
return (val, bs) -> {
237+
if (bs instanceof ArrayBindingSet) {
238+
directAccessForVariable.accept(val, (ArrayBindingSet) bs);
239+
} else {
240+
bs.setBinding(variableName, val);
241+
}
242+
};
243+
} else {
244+
return (val, bs) -> bs.setBinding(variableName, val);
245+
}
229246
}
230247

231248
@Override
@@ -240,13 +257,17 @@ public BiConsumer<Value, MutableBindingSet> addBinding(String variableName) {
240257

241258
BiConsumer<Value, ArrayBindingSet> wrapped = defaultArrayBindingSet
242259
.getDirectAddBinding(variableName);
243-
return (val, bs) -> {
244-
if (bs instanceof ArrayBindingSet) {
245-
wrapped.accept(val, (ArrayBindingSet) bs);
246-
} else {
247-
bs.addBinding(variableName, val);
248-
}
249-
};
260+
if (wrapped != null) {
261+
return (val, bs) -> {
262+
if (bs instanceof ArrayBindingSet) {
263+
wrapped.accept(val, (ArrayBindingSet) bs);
264+
} else {
265+
bs.addBinding(variableName, val);
266+
}
267+
};
268+
} else {
269+
return (val, bs) -> bs.addBinding(variableName, val);
270+
}
250271
}
251272

252273
@Override

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

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.concurrent.TimeUnit;
1818
import java.util.function.BiFunction;
1919
import java.util.function.Consumer;
20+
import java.util.function.Predicate;
2021
import java.util.function.Supplier;
2122

2223
import org.eclipse.rdf4j.collection.factory.api.CollectionFactory;
@@ -616,29 +617,8 @@ protected QueryEvaluationStep prepare(Service service, QueryEvaluationContext co
616617

617618
protected QueryEvaluationStep prepare(Filter node, QueryEvaluationContext context) throws QueryEvaluationException {
618619

619-
QueryEvaluationStep arg = precompile(node.getArg(), context);
620-
QueryValueEvaluationStep ves;
621-
try {
622-
ves = precompile(node.getCondition(), context);
623-
} catch (QueryEvaluationException e) {
624-
// If we have a failed compilation we always return false.
625-
// Which means empty. so let's short circuit that.
626-
// ves = new QueryValueEvaluationStep.ConstantQueryValueEvaluationStep(BooleanLiteral.FALSE);
627-
return bs -> QueryEvaluationStep.EMPTY_ITERATION;
628-
}
629-
return bs -> {
630-
CloseableIteration<BindingSet> evaluate = null;
631-
try {
632-
evaluate = arg.evaluate(bs);
633-
return new FilterIterator(evaluate, ves, DefaultEvaluationStrategy.this);
634-
} catch (Throwable t) {
635-
if (evaluate != null) {
636-
evaluate.close();
637-
}
638-
throw t;
639-
}
620+
return FilterIterator.supply(node, DefaultEvaluationStrategy.this, context);
640621

641-
};
642622
}
643623

644624
protected QueryEvaluationStep prepare(Order node, QueryEvaluationContext context) throws QueryEvaluationException {
@@ -939,12 +919,13 @@ protected QueryValueEvaluationStep prepare(Var var, QueryEvaluationContext conte
939919
return new ConstantQueryValueEvaluationStep(value);
940920
} else {
941921
java.util.function.Function<BindingSet, Value> getValue = context.getValue(var.getName());
922+
Predicate<BindingSet> hasValue = context.hasBinding(var.getName());
942923
return bindings -> {
943-
Value value1 = getValue.apply(bindings);
944-
if (value1 == null) {
924+
if (hasValue.test(bindings)) {
925+
return getValue.apply(bindings);
926+
} else {
945927
throw new ValueExprEvaluationException();
946928
}
947-
return value1;
948929
};
949930
}
950931

0 commit comments

Comments
 (0)