Skip to content

Commit 6b54eed

Browse files
committed
working on new ID based join iterator
1 parent 81a7e40 commit 6b54eed

13 files changed

Lines changed: 268 additions & 88 deletions

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbDelegatingSailDataset.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,36 +95,51 @@ public RecordIterator getRecordIterator(org.eclipse.rdf4j.query.algebra.Statemen
9595
@Override
9696
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
9797
long[] patternIds) throws QueryEvaluationException {
98-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null);
98+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null, null);
9999
}
100100

101101
@Override
102102
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
103103
long[] patternIds, long[] reuse) throws QueryEvaluationException {
104+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, null);
105+
}
106+
107+
@Override
108+
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
109+
long[] patternIds, long[] reuse, long[] quadReuse) throws QueryEvaluationException {
104110
if (delegate instanceof LmdbEvaluationDataset) {
105111
return ((LmdbEvaluationDataset) delegate).getRecordIterator(binding, subjIndex, predIndex, objIndex,
106-
ctxIndex, patternIds, reuse);
112+
ctxIndex, patternIds, reuse, quadReuse);
107113
}
108114
// Fallback via TripleSource with Value conversion
109115
return new LmdbSailDatasetTripleSource(valueStore, delegate)
110-
.getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse);
116+
.getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, quadReuse);
111117
}
112118

113119
@Override
114120
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
115121
int ctxIndex, long[] patternIds, StatementOrder order) throws QueryEvaluationException {
116-
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, null);
122+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, null,
123+
null);
117124
}
118125

119126
@Override
120127
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
121128
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse) throws QueryEvaluationException {
129+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, reuse,
130+
null);
131+
}
132+
133+
@Override
134+
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
135+
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse, long[] quadReuse)
136+
throws QueryEvaluationException {
122137
if (delegate instanceof LmdbEvaluationDataset) {
123138
return ((LmdbEvaluationDataset) delegate).getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex,
124-
ctxIndex, patternIds, order, reuse);
139+
ctxIndex, patternIds, order, reuse, quadReuse);
125140
}
126141
return LmdbEvaluationDataset.super.getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex,
127-
patternIds, order, reuse);
142+
patternIds, order, reuse, quadReuse);
128143
}
129144

130145
@Override

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbDupRecordIterator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class LmdbDupRecordIterator implements RecordIterator {
4242

4343
@FunctionalInterface
4444
interface FallbackSupplier {
45-
RecordIterator get() throws IOException;
45+
RecordIterator get(long[] quadReuse) throws IOException;
4646
}
4747

4848
/** Toggle copying of duplicate blocks for extra safety (defaults to copying). */
@@ -390,6 +390,6 @@ private RecordIterator createFallback() throws IOException {
390390
if (fallbackSupplier == null) {
391391
return null;
392392
}
393-
return fallbackSupplier.get();
393+
return fallbackSupplier.get(quad);
394394
}
395395
}

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbEvaluationDataset.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,24 @@ RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, i
6262
long[] patternIds) throws QueryEvaluationException;
6363

6464
/**
65-
* Variant of {@link #getRecordIterator(long[], int, int, int, int, long[])} that allows callers to supply a
66-
* reusable scratch buffer. Implementations should treat {@code binding} as read-only and (when {@code reuse} is
65+
* Variant of {@link #getRecordIterator(long[], int, int, int, int, long[])} that allows callers to supply reusable
66+
* scratch buffers. Implementations should treat {@code binding} as read-only and (when {@code bindingReuse} is
6767
* non-null and large enough) seed the scratch buffer with the binding state before producing rows from this
68-
* iterator.
68+
* iterator. The {@code quadReuse} buffer (length 4) can be forwarded to iterators that materialize raw quadruples
69+
* from the underlying store.
6970
*
70-
* @param reuse optional scratch buffer that may be mutated and returned from {@link RecordIterator#next()}
71+
* @param bindingReuse optional binding scratch buffer returned from {@link RecordIterator#next()}
72+
* @param quadReuse optional quad scratch buffer (length 4)
7173
*/
7274
@InternalUseOnly
7375
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
74-
long[] patternIds, long[] reuse) throws QueryEvaluationException {
76+
long[] patternIds, long[] bindingReuse) throws QueryEvaluationException {
77+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, bindingReuse, null);
78+
}
79+
80+
@InternalUseOnly
81+
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
82+
long[] patternIds, long[] bindingReuse, long[] quadReuse) throws QueryEvaluationException {
7583
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds);
7684
}
7785

@@ -96,7 +104,18 @@ default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, i
96104
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
97105
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse) throws QueryEvaluationException {
98106
if (order == null) {
99-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse);
107+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, null);
108+
}
109+
return null;
110+
}
111+
112+
@InternalUseOnly
113+
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
114+
int ctxIndex, long[] patternIds, StatementOrder order, long[] bindingReuse, long[] quadReuse)
115+
throws QueryEvaluationException {
116+
if (order == null) {
117+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, bindingReuse,
118+
quadReuse);
100119
}
101120
return null;
102121
}

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbIdTripleSource.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,15 @@ RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, i
3434
long[] patternIds) throws QueryEvaluationException;
3535

3636
/**
37-
* Variant that accepts a reusable scratch buffer.
37+
* Variant that accepts reusable scratch buffers for bindings and quads.
3838
*/
3939
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
40-
long[] patternIds, long[] reuse) throws QueryEvaluationException {
40+
long[] patternIds, long[] bindingReuse) throws QueryEvaluationException {
41+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, bindingReuse, null);
42+
}
43+
44+
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
45+
long[] patternIds, long[] bindingReuse, long[] quadReuse) throws QueryEvaluationException {
4146
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds);
4247
}
4348

@@ -53,12 +58,22 @@ default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, i
5358
}
5459

5560
/**
56-
* Variant that accepts a reusable scratch buffer.
61+
* Variant that accepts reusable scratch buffers.
5762
*/
5863
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
5964
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse) throws QueryEvaluationException {
6065
if (order == null) {
61-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse);
66+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, null);
67+
}
68+
return null;
69+
}
70+
71+
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
72+
int ctxIndex, long[] patternIds, StatementOrder order, long[] bindingReuse, long[] quadReuse)
73+
throws QueryEvaluationException {
74+
if (order == null) {
75+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, bindingReuse,
76+
quadReuse);
6277
}
6378
return null;
6479
}

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbIdTripleSourceAdapter.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,31 @@ public ValueFactory getValueFactory() {
8282
@Override
8383
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
8484
long[] patternIds) throws QueryEvaluationException {
85-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null);
85+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null, null);
8686
}
8787

8888
@Override
8989
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
9090
long[] patternIds, long[] reuse) throws QueryEvaluationException {
91+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, null);
92+
}
93+
94+
@Override
95+
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
96+
long[] patternIds, long[] reuse, long[] quadReuse) throws QueryEvaluationException {
9197
// Prefer direct ID-level access if the delegate already supports it
9298
if (delegate instanceof LmdbIdTripleSource) {
9399
return ((LmdbIdTripleSource) delegate).getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex,
94-
patternIds, reuse);
100+
patternIds, reuse, quadReuse);
95101
}
96102

97103
// If no active connection changes, delegate to the current LMDB dataset to avoid materialization
98104
if (!LmdbEvaluationStrategy.hasActiveConnectionChanges()) {
99105
var dsOpt = LmdbEvaluationStrategy.getCurrentDataset();
100106
if (dsOpt.isPresent()) {
101107
return dsOpt.get()
102-
.getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds,
103-
reuse);
108+
.getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse,
109+
quadReuse);
104110
}
105111
}
106112

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbOverlayEvaluationDataset.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,20 +131,26 @@ public void close() {
131131
@Override
132132
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
133133
long[] patternIds) throws QueryEvaluationException {
134-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null);
134+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null, null);
135135
}
136136

137137
@Override
138138
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
139139
long[] patternIds, long[] reuse) throws QueryEvaluationException {
140+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, null);
141+
}
142+
143+
@Override
144+
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
145+
long[] patternIds, long[] reuse, long[] quadReuse) throws QueryEvaluationException {
140146
// Fast path: no active connection changes → use the current LMDB dataset's ID-level iterator
141147
try {
142148
if (!LmdbEvaluationStrategy.hasActiveConnectionChanges()) {
143149
var dsOpt = LmdbEvaluationStrategy.getCurrentDataset();
144150
if (dsOpt.isPresent()) {
145151
return dsOpt.get()
146152
.getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds,
147-
reuse);
153+
reuse, quadReuse);
148154
}
149155
}
150156
} catch (Exception ignore) {
@@ -156,7 +162,7 @@ public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predI
156162
// current branch dataset state (including transaction overlays). Therefore, using ID-level access here is
157163
// correct when available.
158164
RecordIterator viaIds = ((LmdbIdTripleSource) tripleSource)
159-
.getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse);
165+
.getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, quadReuse);
160166
if (viaIds != null) {
161167
return viaIds;
162168
}
@@ -249,14 +255,22 @@ public void close() {
249255
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
250256
int ctxIndex, long[] patternIds, StatementOrder order) throws QueryEvaluationException {
251257
return LmdbEvaluationDataset.super.getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex,
252-
patternIds, order);
258+
patternIds, order, null, null);
253259
}
254260

255261
@Override
256262
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
257263
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse) throws QueryEvaluationException {
258264
return LmdbEvaluationDataset.super.getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex,
259-
patternIds, order, reuse);
265+
patternIds, order, reuse, null);
266+
}
267+
268+
@Override
269+
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
270+
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse, long[] quadReuse)
271+
throws QueryEvaluationException {
272+
return LmdbEvaluationDataset.super.getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex,
273+
patternIds, order, reuse, quadReuse);
260274
}
261275

262276
@Override

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbRecordIterator.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ class LmdbRecordIterator implements RecordIterator {
8686
private int lastResult;
8787

8888
private final long[] quad;
89-
private final long[] originalQuad;
9089

9190
private boolean fetchNext = false;
9291

@@ -96,17 +95,34 @@ class LmdbRecordIterator implements RecordIterator {
9695

9796
LmdbRecordIterator(TripleIndex index, boolean rangeSearch, long subj, long pred, long obj,
9897
long context, boolean explicit, Txn txnRef) throws IOException {
99-
this(index, null, rangeSearch, subj, pred, obj, context, explicit, txnRef);
98+
this(index, null, rangeSearch, subj, pred, obj, context, explicit, txnRef, null);
99+
}
100+
101+
LmdbRecordIterator(TripleIndex index, boolean rangeSearch, long subj, long pred, long obj,
102+
long context, boolean explicit, Txn txnRef, long[] quadReuse) throws IOException {
103+
this(index, null, rangeSearch, subj, pred, obj, context, explicit, txnRef, quadReuse);
100104
}
101105

102106
LmdbRecordIterator(TripleIndex index, KeyBuilder keyBuilder, boolean rangeSearch, long subj,
103107
long pred, long obj, long context, boolean explicit, Txn txnRef) throws IOException {
108+
this(index, keyBuilder, rangeSearch, subj, pred, obj, context, explicit, txnRef, null);
109+
}
110+
111+
LmdbRecordIterator(TripleIndex index, KeyBuilder keyBuilder, boolean rangeSearch, long subj,
112+
long pred, long obj, long context, boolean explicit, Txn txnRef, long[] quadReuse) throws IOException {
104113
this.subj = subj;
105114
this.pred = pred;
106115
this.obj = obj;
107116
this.context = context;
108-
this.originalQuad = new long[] { subj, pred, obj, context };
109-
this.quad = new long[] { subj, pred, obj, context };
117+
if (quadReuse != null && quadReuse.length >= 4) {
118+
this.quad = quadReuse;
119+
this.quad[0] = subj;
120+
this.quad[1] = pred;
121+
this.quad[2] = obj;
122+
this.quad[3] = context;
123+
} else {
124+
this.quad = new long[] { subj, pred, obj, context };
125+
}
110126
this.pool = Pool.get();
111127
this.keyData = pool.getVal();
112128
this.valueData = pool.getVal();
@@ -266,7 +282,7 @@ public long[] next() {
266282
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_NEXT);
267283
} else {
268284
// Matching value found
269-
index.keyToQuad(keyData.mv_data(), originalQuad, quad);
285+
index.keyToQuad(keyData.mv_data(), subj, pred, obj, context, quad);
270286
// fetch next value
271287
fetchNext = true;
272288
return quad;

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbSailDatasetTripleSource.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,23 @@ public LmdbSailDatasetTripleSource(ValueFactory vf, SailDataset dataset) {
4343
@Override
4444
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
4545
long[] patternIds) throws QueryEvaluationException {
46-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null);
46+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null, null);
4747
}
4848

4949
@Override
5050
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
5151
long[] patternIds, long[] reuse) throws QueryEvaluationException {
52+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, null);
53+
}
54+
55+
@Override
56+
public RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
57+
long[] patternIds, long[] reuse, long[] quadReuse) throws QueryEvaluationException {
5258

5359
// Fast path: backing dataset supports ID-level access
5460
if (dataset instanceof LmdbEvaluationDataset) {
5561
return ((LmdbEvaluationDataset) dataset).getRecordIterator(binding, subjIndex, predIndex, objIndex,
56-
ctxIndex, patternIds, reuse);
62+
ctxIndex, patternIds, reuse, quadReuse);
5763
}
5864

5965
// Fallback path: value-level iteration converted to IDs using ValueStore
@@ -152,18 +158,27 @@ public void close() {
152158
@Override
153159
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
154160
int ctxIndex, long[] patternIds, StatementOrder order) throws QueryEvaluationException {
155-
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, null);
161+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, null,
162+
null);
156163
}
157164

158165
@Override
159166
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
160167
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse) throws QueryEvaluationException {
168+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, reuse,
169+
null);
170+
}
171+
172+
@Override
173+
public RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
174+
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse, long[] quadReuse)
175+
throws QueryEvaluationException {
161176
if (dataset instanceof LmdbEvaluationDataset) {
162177
return ((LmdbEvaluationDataset) dataset).getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex,
163-
ctxIndex, patternIds, order, reuse);
178+
ctxIndex, patternIds, order, reuse, quadReuse);
164179
}
165180
return LmdbIdTripleSource.super.getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex,
166-
patternIds, order, reuse);
181+
patternIds, order, reuse, quadReuse);
167182
}
168183

169184
private long selectQueryId(long patternId, long[] binding, int index) {

0 commit comments

Comments
 (0)