Skip to content

Commit 7812d82

Browse files
committed
working on new ID based join iterator
1 parent 6b54eed commit 7812d82

15 files changed

Lines changed: 1095 additions & 267 deletions

core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/StatementPattern.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,77 @@ public enum Scope {
4848
NAMED_CONTEXTS
4949
}
5050

51+
/**
52+
* Index selection hint for statement pattern evaluation.
53+
*/
54+
@Experimental
55+
public enum Index {
56+
S,
57+
P,
58+
O,
59+
C,
60+
SP,
61+
SO,
62+
SC,
63+
PS,
64+
PO,
65+
PC,
66+
OS,
67+
OP,
68+
OC,
69+
CS,
70+
CP,
71+
CO,
72+
SPO,
73+
SPC,
74+
SOP,
75+
SOC,
76+
SCP,
77+
SCO,
78+
PSO,
79+
PSC,
80+
POS,
81+
POC,
82+
PCS,
83+
PCO,
84+
OSP,
85+
OSC,
86+
OPS,
87+
OPC,
88+
OCS,
89+
OCP,
90+
CSP,
91+
CSO,
92+
CPS,
93+
CPO,
94+
COS,
95+
COP,
96+
SPOC,
97+
SPCO,
98+
SOPC,
99+
SOCP,
100+
SCPO,
101+
SCOP,
102+
PSOC,
103+
PSCO,
104+
POSC,
105+
POCS,
106+
PCSO,
107+
PCOS,
108+
OSPC,
109+
OSCP,
110+
OPSC,
111+
OPCS,
112+
OCSP,
113+
OCPS,
114+
CSPO,
115+
CSOP,
116+
CPSO,
117+
CPOS,
118+
COSP,
119+
COPS
120+
}
121+
51122
/*-----------*
52123
* Variables *
53124
*-----------*/
@@ -66,6 +137,8 @@ public enum Scope {
66137

67138
private String indexName;
68139

140+
private Index index;
141+
69142
private Set<String> assuredBindingNames;
70143
private List<Var> varList;
71144

@@ -427,6 +500,7 @@ public StatementPattern clone() {
427500
clone.assuredBindingNames = assuredBindingNames;
428501
clone.varList = null;
429502
clone.statementOrder = statementOrder;
503+
clone.index = index;
430504

431505
return clone;
432506
}
@@ -540,8 +614,18 @@ public String getIndexName() {
540614
return indexName;
541615
}
542616

617+
@Experimental
618+
public Index getIndex() {
619+
return index;
620+
}
621+
543622
@Experimental
544623
public void setIndexName(String indexName) {
545624
this.indexName = indexName;
546625
}
626+
627+
@Experimental
628+
public void setIndex(Index index) {
629+
this.index = index;
630+
}
547631
}

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

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

4343
@FunctionalInterface
4444
interface FallbackSupplier {
45-
RecordIterator get(long[] quadReuse) throws IOException;
45+
RecordIterator get(long[] quadReuse, ByteBuffer minKeyBuf, ByteBuffer maxKeyBuf,
46+
LmdbRecordIterator iteratorReuse)
47+
throws IOException;
4648
}
4749

4850
/** Toggle copying of duplicate blocks for extra safety (defaults to copying). */
@@ -390,6 +392,6 @@ private RecordIterator createFallback() throws IOException {
390392
if (fallbackSupplier == null) {
391393
return null;
392394
}
393-
return fallbackSupplier.get(quad);
395+
return fallbackSupplier.get(quad, null, null, null);
394396
}
395397
}

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

Lines changed: 111 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
*******************************************************************************/
1111
package org.eclipse.rdf4j.sail.lmdb;
1212

13+
import java.nio.ByteBuffer;
14+
1315
import org.eclipse.rdf4j.common.annotation.InternalUseOnly;
1416
import org.eclipse.rdf4j.common.order.StatementOrder;
1517
import org.eclipse.rdf4j.common.transaction.IsolationLevel;
@@ -22,6 +24,30 @@
2224
*/
2325
public interface LmdbEvaluationDataset {
2426

27+
@InternalUseOnly
28+
final class KeyRangeBuffers {
29+
private final ByteBuffer minKey;
30+
private final ByteBuffer maxKey;
31+
32+
public KeyRangeBuffers(ByteBuffer minKey, ByteBuffer maxKey) {
33+
this.minKey = minKey;
34+
this.maxKey = maxKey;
35+
}
36+
37+
public static KeyRangeBuffers acquire() {
38+
Pool pool = Pool.get();
39+
return new KeyRangeBuffers(pool.getKeyBuffer(), pool.getKeyBuffer());
40+
}
41+
42+
public ByteBuffer minKey() {
43+
return minKey;
44+
}
45+
46+
public ByteBuffer maxKey() {
47+
return maxKey;
48+
}
49+
}
50+
2551
/**
2652
* Create a {@link RecordIterator} for the supplied {@link StatementPattern}, taking into account any existing
2753
* bindings.
@@ -33,6 +59,21 @@ public interface LmdbEvaluationDataset {
3359
*/
3460
RecordIterator getRecordIterator(StatementPattern pattern, BindingSet bindings) throws QueryEvaluationException;
3561

62+
@InternalUseOnly
63+
default RecordIterator getRecordIterator(StatementPattern pattern, BindingSet bindings, KeyRangeBuffers keyBuffers)
64+
throws QueryEvaluationException {
65+
return getRecordIterator(pattern, bindings);
66+
}
67+
68+
@InternalUseOnly
69+
default RecordIterator getRecordIterator(StatementPattern pattern, BindingSet bindings, KeyRangeBuffers keyBuffers,
70+
RecordIterator iteratorReuse) throws QueryEvaluationException {
71+
if (iteratorReuse != null) {
72+
iteratorReuse.close();
73+
}
74+
return getRecordIterator(pattern, bindings, keyBuffers);
75+
}
76+
3677
/**
3778
* Create a {@link RecordIterator} for the supplied pattern, expressed as internal IDs, using the current binding
3879
* snapshot.
@@ -61,6 +102,12 @@ public interface LmdbEvaluationDataset {
61102
RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
62103
long[] patternIds) throws QueryEvaluationException;
63104

105+
@InternalUseOnly
106+
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
107+
long[] patternIds, KeyRangeBuffers keyBuffers) throws QueryEvaluationException {
108+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds);
109+
}
110+
64111
/**
65112
* Variant of {@link #getRecordIterator(long[], int, int, int, int, long[])} that allows callers to supply reusable
66113
* scratch buffers. Implementations should treat {@code binding} as read-only and (when {@code bindingReuse} is
@@ -74,26 +121,45 @@ RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, i
74121
@InternalUseOnly
75122
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
76123
long[] patternIds, long[] bindingReuse) throws QueryEvaluationException {
77-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, bindingReuse, null);
124+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null, bindingReuse,
125+
null);
78126
}
79127

80128
@InternalUseOnly
81129
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
82130
long[] patternIds, long[] bindingReuse, long[] quadReuse) throws QueryEvaluationException {
131+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, null, bindingReuse,
132+
quadReuse);
133+
}
134+
135+
@InternalUseOnly
136+
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
137+
long[] patternIds, KeyRangeBuffers keyBuffers, long[] bindingReuse, long[] quadReuse)
138+
throws QueryEvaluationException {
83139
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds);
84140
}
85141

142+
@InternalUseOnly
143+
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
144+
long[] patternIds, KeyRangeBuffers keyBuffers, long[] bindingReuse, long[] quadReuse,
145+
RecordIterator iteratorReuse)
146+
throws QueryEvaluationException {
147+
if (iteratorReuse != null) {
148+
iteratorReuse.close();
149+
}
150+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, keyBuffers,
151+
bindingReuse, quadReuse);
152+
}
153+
86154
/**
87155
* Create an ordered {@link RecordIterator} for the supplied pattern expressed via internal IDs and binding indexes.
88156
* Implementations may fall back to the unordered iterator when the requested order is unsupported.
89157
*/
90158
@InternalUseOnly
91159
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
92160
int ctxIndex, long[] patternIds, StatementOrder order) throws QueryEvaluationException {
93-
if (order == null) {
94-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds);
95-
}
96-
return null;
161+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, null,
162+
null, null);
97163
}
98164

99165
/**
@@ -103,31 +169,54 @@ default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, i
103169
@InternalUseOnly
104170
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
105171
int ctxIndex, long[] patternIds, StatementOrder order, long[] reuse) throws QueryEvaluationException {
106-
if (order == null) {
107-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, reuse, null);
108-
}
109-
return null;
172+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, null,
173+
reuse, null);
110174
}
111175

112176
@InternalUseOnly
113177
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
114178
int ctxIndex, long[] patternIds, StatementOrder order, long[] bindingReuse, long[] quadReuse)
115179
throws QueryEvaluationException {
180+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order, null,
181+
bindingReuse, quadReuse);
182+
}
183+
184+
@InternalUseOnly
185+
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
186+
int ctxIndex, long[] patternIds, StatementOrder order, KeyRangeBuffers keyBuffers, long[] bindingReuse,
187+
long[] quadReuse) throws QueryEvaluationException {
116188
if (order == null) {
117-
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, bindingReuse,
118-
quadReuse);
189+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, keyBuffers,
190+
bindingReuse, quadReuse);
119191
}
120192
return null;
121193
}
122194

195+
@InternalUseOnly
196+
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
197+
int ctxIndex, long[] patternIds, StatementOrder order, KeyRangeBuffers keyBuffers, long[] bindingReuse,
198+
long[] quadReuse, RecordIterator iteratorReuse) throws QueryEvaluationException {
199+
if (iteratorReuse != null) {
200+
iteratorReuse.close();
201+
}
202+
return getOrderedRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, order,
203+
keyBuffers,
204+
bindingReuse, quadReuse);
205+
}
206+
123207
/**
124208
* Create an ordered {@link RecordIterator} for the supplied pattern. Implementations may fall back to the unordered
125209
* iterator when the requested order is unsupported.
126210
*/
127211
default RecordIterator getOrderedRecordIterator(StatementPattern pattern, BindingSet bindings, StatementOrder order)
128212
throws QueryEvaluationException {
213+
return getOrderedRecordIterator(pattern, bindings, order, null);
214+
}
215+
216+
default RecordIterator getOrderedRecordIterator(StatementPattern pattern, BindingSet bindings, StatementOrder order,
217+
KeyRangeBuffers keyBuffers) throws QueryEvaluationException {
129218
if (order == null) {
130-
return getRecordIterator(pattern, bindings);
219+
return getRecordIterator(pattern, bindings, keyBuffers);
131220
}
132221
return null;
133222
}
@@ -137,6 +226,16 @@ default boolean supportsOrder(long[] binding, int subjIndex, int predIndex, int
137226
return order == null;
138227
}
139228

229+
/**
230+
* Determine the most suitable LMDB index for the supplied binding pattern.
231+
*
232+
* @return the field sequence of the selected index (e.g. {@code \"spoc\"}), or {@code null} when no advice is
233+
* available
234+
*/
235+
default String selectBestIndex(long subj, long pred, long obj, long context) {
236+
return null;
237+
}
238+
140239
/**
141240
* @return the {@link ValueStore} backing this dataset.
142241
*/

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public interface LmdbIdTripleSource {
3333
RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
3434
long[] patternIds) throws QueryEvaluationException;
3535

36+
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
37+
long[] patternIds, LmdbEvaluationDataset.KeyRangeBuffers keyBuffers) throws QueryEvaluationException {
38+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds);
39+
}
40+
3641
/**
3742
* Variant that accepts reusable scratch buffers for bindings and quads.
3843
*/
@@ -46,6 +51,13 @@ default RecordIterator getRecordIterator(long[] binding, int subjIndex, int pred
4651
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds);
4752
}
4853

54+
default RecordIterator getRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex, int ctxIndex,
55+
long[] patternIds, LmdbEvaluationDataset.KeyRangeBuffers keyBuffers, long[] bindingReuse, long[] quadReuse)
56+
throws QueryEvaluationException {
57+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, bindingReuse,
58+
quadReuse);
59+
}
60+
4961
/**
5062
* Create an ordered iterator over ID-level bindings; may fall back to the unordered iterator if unsupported.
5163
*/
@@ -77,4 +89,14 @@ default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, i
7789
}
7890
return null;
7991
}
92+
93+
default RecordIterator getOrderedRecordIterator(long[] binding, int subjIndex, int predIndex, int objIndex,
94+
int ctxIndex, long[] patternIds, StatementOrder order, LmdbEvaluationDataset.KeyRangeBuffers keyBuffers,
95+
long[] bindingReuse, long[] quadReuse) throws QueryEvaluationException {
96+
if (order == null) {
97+
return getRecordIterator(binding, subjIndex, predIndex, objIndex, ctxIndex, patternIds, keyBuffers,
98+
bindingReuse, quadReuse);
99+
}
100+
return null;
101+
}
80102
}

0 commit comments

Comments
 (0)