This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new d560c7829d GH-3516: Removed needless multiHashProbleTable.clear() from
AbstractIterHashJoin.close().
d560c7829d is described below
commit d560c7829dc3f8040325e9ac0dd9c5a7320e6c6c
Author: Claus Stadler <[email protected]>
AuthorDate: Fri Oct 17 13:24:54 2025 +0200
GH-3516: Removed needless multiHashProbleTable.clear() from
AbstractIterHashJoin.close().
---
.../jena/sparql/engine/join/AbstractIterHashJoin.java | 16 ++++++++++------
.../org/apache/jena/sparql/engine/join/JoinIndex.java | 15 +++++++++++++--
.../jena/sparql/engine/join/MultiHashProbeTable.java | 16 ++++++++--------
.../jena/sparql/engine/join/AbstractTestInnerJoin.java | 5 +++++
4 files changed, 36 insertions(+), 16 deletions(-)
diff --git
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/AbstractIterHashJoin.java
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/AbstractIterHashJoin.java
index 126be65a85..4da1392983 100644
---
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/AbstractIterHashJoin.java
+++
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/AbstractIterHashJoin.java
@@ -44,14 +44,16 @@ public abstract class AbstractIterHashJoin extends
QueryIter2 {
// See also stats in the probe table.
protected JoinKey joinKey ;
- protected MultiHashProbeTable hashTable ;
+
+ // HashTable is initialized lazily.
+ protected MultiHashProbeTable hashTable = null ;
private QueryIterator iterStream ;
- private Binding rowStream = null ;
+ private Binding rowStream = null ;
private Iterator<Binding> iterCurrent ;
private boolean yielded ; // Flag to note when
current probe causes a result.
// Hanlde any "post join" additions.
- private Iterator<Binding> iterTail = null ;
+ private Iterator<Binding> iterTail = null ;
enum Phase { INIT, HASH , STREAM, TRAILER, DONE }
Phase state = Phase.INIT ;
@@ -234,13 +236,15 @@ public abstract class AbstractIterHashJoin extends
QueryIter2 {
if ( JoinLib.JOIN_EXPLAIN ) {
String x = String.format(
"HashJoin: LHS=%d RHS=%d Results=%d Table=%s",
- s_countProbe, s_countScan, s_countResults,
- hashTable.toString()) ;
+ s_countProbe, s_countScan, s_countResults, hashTable)
;
System.out.println(x) ;
}
// In case it's a peek iterator.
iterStream.close() ;
- hashTable.clear();
+ if ( hashTable != null ) {
+ hashTable.clear() ;
+ hashTable = null ;
+ }
}
@Override
diff --git
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinIndex.java
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinIndex.java
index e66d28ba94..0c80adefca 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinIndex.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinIndex.java
@@ -41,14 +41,21 @@ import org.slf4j.LoggerFactory;
/**
* This class indexes a set of rows w.r.t. a join key, referred to as the
<i>main join key</i>.
- * <p />
+ * <p>
* Consider the main join key [?x, ?y, ?z]:
- * <p />
* All rows that bind all three variables will be placed into the main table.
*
+ * <p>
* Any rows that only bind a sub set of the variables, such as [?x, ?z] or
[?y],
* are placed into respective skew tables.
*
+ * <p>
+ * The super join determines the bit set representation of the the main and
skew join keys.
+ * It and must declare at least all variables of the main join key.
+ * For example, given the super join key [?a, ?x, ?y, ?b ?z] the
aforementioned main join key
+ * becomes represented with the bit pattern [0, 1, 1, 0, 1].
+ *
+ * <p>
* JoinIndex instances are dynamically created by {@link MultiHashProbeTable}
based on the
* variables of the bindings used in lookup requests for matching rows.
*
@@ -84,6 +91,10 @@ class JoinIndex
this.mainTable = new HashProbeTable(mainJoinKey);
}
+ public JoinKey getSuperJoinKey() {
+ return superJoinKey;
+ }
+
public BitSet getMainJoinKeyBitSet() {
return mainJoinKeyBitSet;
}
diff --git
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/MultiHashProbeTable.java
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/MultiHashProbeTable.java
index 0333854f94..41552ff496 100644
---
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/MultiHashProbeTable.java
+++
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/MultiHashProbeTable.java
@@ -69,7 +69,7 @@ class MultiHashProbeTable
private final JoinIndex initialIndex;
/** Tables for hash lookups. Will be created dynamically during {@link
#getCandidates(Binding)}. */
- private final Map<BitSet, JoinIndex> indexes = new HashMap<>();
+ private final Map<BitSet, JoinIndex> indexes = new HashMap<>();
/** The set of seen variables across all rows */
private final Set<Var> seenVarSet = new LinkedHashSet<>();
@@ -92,10 +92,6 @@ class MultiHashProbeTable
initialJoinKey = JoinKey.empty();
}
- // If an initial join key is given then its variables are added to
seen vars
- // so that those correspond to the first bits of the bit keys
- seenVarSet.addAll(initialJoinKey);
-
int nbits = initialJoinKey.size();
BitSet initialJoinKeyBitset = new BitSet(nbits);
initialJoinKeyBitset.flip(0, nbits);
@@ -129,7 +125,7 @@ class MultiHashProbeTable
initialIndex.put(row);
}
- /** Update seen vars with the row's relevant variables w.r.t. an optional
rootJoinKey. */
+ /** Update seen vars with the row's relevant variables w.r.t. an optional
maxJoinKey. */
private void updateSeenVars(Binding row) {
if (maxJoinKey == null) {
row.vars().forEachRemaining(seenVarSet::add);
@@ -180,9 +176,13 @@ class MultiHashProbeTable
* This method is package private so that it can be called from tests.
*/
void doFinalize() {
- // Note: We need to stick with the variable order provided in the
initial index -> don't sort!
+ // If an initial join key is given then its variables are prepended to
seen vars
+ // so that those correspond to the first bits of the bit keys!
+ // This means we need to stick with the variable order provided in the
initial index
+ // -> don't sort!
// Arrays.sort(seenVars, (a, b) -> a.getName().compareTo(b.getName()));
- seenVarsJoinKey = JoinKey.create(seenVarSet);
+ seenVarsJoinKey = JoinKey.newBuilder()
+ .addAll(initialIndex.getSuperJoinKey()).addAll(seenVarSet).build();
indexes.put(initialIndex.getMainJoinKeyBitSet(), initialIndex);
isFinalized = true;
}
diff --git
a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java
b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java
index 74ee491a31..ad5f4f7873 100644
---
a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java
+++
b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java
@@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test;
import org.apache.jena.sparql.algebra.Table;
import org.apache.jena.sparql.core.Var;
+import org.apache.jena.sparql.engine.QueryIterator;
import org.apache.jena.sparql.expr.ExprList;
/** Tests for inner/equi joins */
@@ -80,6 +81,10 @@ public abstract class AbstractTestInnerJoin extends
AbstractTestJoin {
@Test public void join_skew_02b() { testJoin("w", tableS1b(), tableS2(),
tableS1J2()); }
@Test public void join_skew_03b() { testJoin(null, tableS1b(), tableS2(),
tableS1J2()); }
+ @Test public void testCloseOfUnusedIterator() {
+ QueryIterator qIter = join(null, table1() , table1(), null);
+ qIter.close();
+ }
@Test
public void join_skew_04() {