Skip to content

Commit 9894f00

Browse files
committed
wip
1 parent 8114dce commit 9894f00

6 files changed

Lines changed: 232 additions & 7 deletions

File tree

core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BindSelect.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*
99
* SPDX-License-Identifier: BSD-3-Clause
1010
*******************************************************************************/
11+
// Some portions generated by Codex
1112

1213
package org.eclipse.rdf4j.sail.shacl.ast.planNodes;
1314

@@ -58,6 +59,7 @@ public class BindSelect implements PlanNode {
5859
private final SailConnection connection;
5960
private final Dataset dataset;
6061
private final Function<BindingSet, ValidationTuple> mapper;
62+
private final boolean includeInferredStatements;
6163

6264
private final String query;
6365
private final List<Variable<Value>> vars;
@@ -96,6 +98,7 @@ public BindSelect(SailConnection connection, Resource[] dataGraph, SparqlFragmen
9698
this.includePropertyShapeValues = includePropertyShapeValues;
9799

98100
dataset = PlanNodeHelper.asDefaultGraphDataset(dataGraph);
101+
this.includeInferredStatements = connectionsGroup.isIncludeInferredStatements();
99102

100103
// this.stackTrace = Thread.currentThread().getStackTrace();
101104

@@ -240,7 +243,7 @@ public void calculateNext() {
240243
updateQuery(parsedQuery, bindingSets, targetChainSize);
241244

242245
bindingSet = connection.evaluate(parsedQuery, dataset,
243-
EmptyBindingSet.getInstance(), true);
246+
EmptyBindingSet.getInstance(), includeInferredStatements);
244247
}
245248
}
246249

core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ExternalFilterByQuery.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*
99
* SPDX-License-Identifier: BSD-3-Clause
1010
*******************************************************************************/
11+
// Some portions generated by Codex
1112

1213
package org.eclipse.rdf4j.sail.shacl.ast.planNodes;
1314

core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicateObject.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*
99
* SPDX-License-Identifier: BSD-3-Clause
1010
*******************************************************************************/
11+
// Some portions generated by Codex
1112

1213
package org.eclipse.rdf4j.sail.shacl.ast.planNodes;
1314

@@ -270,7 +271,7 @@ private Boolean matchesCached(Resource subject, IRI filterOnPredicate, Resource[
270271
private boolean matchesUnCached(Resource subject, IRI filterOnPredicate, Resource[] filterOnObject) {
271272
for (Resource object : filterOnObject) {
272273
if (connection.hasStatement(subject, filterOnPredicate, object,
273-
includeInferred && !typeFilterWithInference, dataGraph)) {
274+
includeInferred, dataGraph)) {
274275
return true;
275276
}
276277
}

core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/EffectiveTarget.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: BSD-3-Clause
1010
*******************************************************************************/
1111

12+
// Some portions generated by Codex
13+
1214
package org.eclipse.rdf4j.sail.shacl.ast.targets;
1315

1416
import java.util.ArrayDeque;
@@ -195,18 +197,19 @@ public boolean couldMatch(ConnectionsGroup connectionsGroup, Resource[] dataGrap
195197

196198
SailConnection addedStatements = connectionsGroup.getAddedStatements();
197199
SailConnection removedStatements = connectionsGroup.getRemovedStatements();
200+
boolean includeInferredStatements = connectionsGroup.isIncludeInferredStatements();
198201

199202
if (optional != null) {
200203
List<StatementMatcher> statementMatchers = optional.getQueryFragment().getStatementMatchers();
201204
for (StatementMatcher currentStatementPattern : statementMatchers) {
202205
boolean match = addedStatements
203206
.hasStatement(currentStatementPattern.getSubjectValue(),
204207
currentStatementPattern.getPredicateValue(),
205-
currentStatementPattern.getObjectValue(), false, dataGraph)
208+
currentStatementPattern.getObjectValue(), includeInferredStatements, dataGraph)
206209
|| removedStatements
207210
.hasStatement(currentStatementPattern.getSubjectValue(),
208211
currentStatementPattern.getPredicateValue(),
209-
currentStatementPattern.getObjectValue(), false, dataGraph);
212+
currentStatementPattern.getObjectValue(), includeInferredStatements, dataGraph);
210213

211214
if (match) {
212215
return true;
@@ -221,11 +224,11 @@ public boolean couldMatch(ConnectionsGroup connectionsGroup, Resource[] dataGrap
221224
boolean match = addedStatements
222225
.hasStatement(currentStatementPattern.getSubjectValue(),
223226
currentStatementPattern.getPredicateValue(),
224-
currentStatementPattern.getObjectValue(), false, dataGraph)
227+
currentStatementPattern.getObjectValue(), includeInferredStatements, dataGraph)
225228
|| removedStatements
226229
.hasStatement(currentStatementPattern.getSubjectValue(),
227230
currentStatementPattern.getPredicateValue(),
228-
currentStatementPattern.getObjectValue(), false, dataGraph);
231+
currentStatementPattern.getObjectValue(), includeInferredStatements, dataGraph);
229232

230233
if (match) {
231234
return true;

core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/TargetChainRetriever.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: BSD-3-Clause
1010
*******************************************************************************/
1111

12+
// Some portions generated by Codex
13+
1214
package org.eclipse.rdf4j.sail.shacl.ast.targets;
1315

1416
import java.util.ArrayList;
@@ -242,7 +244,8 @@ public void calculateNextStatementMatcher() {
242244
statements = connection.getStatements(
243245
currentStatementMatcher.getSubjectValue(),
244246
currentStatementMatcher.getPredicateValue(),
245-
currentStatementMatcher.getObjectValue(), false, dataGraph);
247+
currentStatementMatcher.getObjectValue(), connectionsGroup.isIncludeInferredStatements(),
248+
dataGraph);
246249

247250
} while (!statements.hasNext());
248251

core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/InferredStatementHandlingConsistencyTest.java

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,39 @@
1212

1313
package org.eclipse.rdf4j.sail.shacl;
1414

15+
import java.util.ArrayDeque;
1516
import java.util.List;
1617
import java.util.NoSuchElementException;
18+
import java.util.Set;
1719

1820
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
1921
import org.eclipse.rdf4j.common.transaction.IsolationLevels;
2022
import org.eclipse.rdf4j.model.IRI;
23+
import org.eclipse.rdf4j.model.Namespace;
2124
import org.eclipse.rdf4j.model.Resource;
2225
import org.eclipse.rdf4j.model.util.Values;
26+
import org.eclipse.rdf4j.model.vocabulary.RDF;
2327
import org.eclipse.rdf4j.model.vocabulary.RDFS;
2428
import org.eclipse.rdf4j.sail.NotifyingSail;
2529
import org.eclipse.rdf4j.sail.SailConnection;
30+
import org.eclipse.rdf4j.sail.inferencer.InferencerConnection;
2631
import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer;
2732
import org.eclipse.rdf4j.sail.memory.MemoryStore;
2833
import org.eclipse.rdf4j.sail.shacl.ast.SparqlFragment;
2934
import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher;
35+
import org.eclipse.rdf4j.sail.shacl.ast.Targetable;
3036
import org.eclipse.rdf4j.sail.shacl.ast.constraintcomponents.ConstraintComponent;
3137
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BindSelect;
3238
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ExternalFilterByQuery;
39+
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.FilterByPredicateObject;
3340
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode;
3441
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.UnBufferedPlanNode;
3542
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ValidationExecutionLogger;
3643
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ValidationTuple;
3744
import org.eclipse.rdf4j.sail.shacl.ast.targets.EffectiveTarget;
45+
import org.eclipse.rdf4j.sail.shacl.ast.targets.TargetChainRetriever;
3846
import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup;
47+
import org.eclipse.rdf4j.sail.shacl.wrapper.data.RdfsSubClassOfReasoner;
3948
import org.junit.jupiter.api.Assertions;
4049
import org.junit.jupiter.api.Test;
4150

@@ -46,7 +55,9 @@ class InferredStatementHandlingConsistencyTest {
4655
private static final IRI TARGET = Values.iri("urn:target");
4756
private static final IRI P = Values.iri("urn:p");
4857
private static final IRI P_SUB = Values.iri("urn:pSub");
58+
private static final IRI DOMAIN_P = Values.iri("urn:domainP");
4959
private static final IRI O = Values.iri("urn:o");
60+
private static final IRI C = Values.iri("urn:c");
5061

5162
@Test
5263
void externalFilterByQueryShouldUseConnectionsGroupIncludeInferredStatements() {
@@ -107,6 +118,182 @@ void bindSelectShouldUseConnectionsGroupIncludeInferredStatements() {
107118
}
108119
}
109120

121+
@Test
122+
void filterByPredicateObjectShouldIncludeInferredTypeStatementsWhenReasonerEnabled() {
123+
try (TestSailContext context = TestSailContext.withInferredTypeFromDomain()) {
124+
try (ConnectionsGroup connectionsGroup = context.connectionsGroup(true, new RdfsSubClassOfReasoner())) {
125+
PlanNode parent = new SingletonPlanNode(
126+
new ValidationTuple(TARGET, ConstraintComponent.Scope.nodeShape, false, ALL_CONTEXTS));
127+
128+
PlanNode accepted = new FilterByPredicateObject(
129+
connectionsGroup.getBaseConnection(),
130+
ALL_CONTEXTS,
131+
RDF.TYPE,
132+
Set.of(C),
133+
parent,
134+
true,
135+
FilterByPredicateObject.FilterOn.activeTarget,
136+
connectionsGroup.isIncludeInferredStatements(),
137+
connectionsGroup
138+
);
139+
140+
Assertions.assertEquals(1, countTuples(accepted),
141+
"Expected inferred rdf:type statements to be visible when includeInferredStatements is enabled");
142+
}
143+
}
144+
}
145+
146+
@Test
147+
void targetChainRetrieverShouldSeeInferredStatementsInAddedStatementsDelta() {
148+
MemoryStore baseStore = new MemoryStore();
149+
baseStore.init();
150+
151+
NotifyingSail addedStatements = new SchemaCachingRDFSInferencer(new MemoryStore(), false);
152+
addedStatements.init();
153+
154+
try (SailConnection baseConnection = baseStore.getConnection()) {
155+
baseConnection.begin(IsolationLevels.NONE);
156+
baseConnection.addStatement(TARGET, P, O);
157+
baseConnection.commit();
158+
baseConnection.begin(IsolationLevels.NONE);
159+
160+
try (InferencerConnection addedConnection = (InferencerConnection) addedStatements.getConnection()) {
161+
addedConnection.begin(IsolationLevels.NONE);
162+
addedConnection.addInferredStatement(TARGET, P, O, (Resource) null);
163+
addedConnection.commit();
164+
}
165+
166+
try (SailConnection checkConnection = addedStatements.getConnection()) {
167+
checkConnection.begin(IsolationLevels.NONE);
168+
Assertions.assertTrue(checkConnection.hasStatement(TARGET, P, O, true, (Resource) null),
169+
"Sanity check: expected inferred statement in added-statements delta to exist");
170+
Assertions.assertFalse(checkConnection.hasStatement(TARGET, P, O, false, (Resource) null),
171+
"Sanity check: expected inferred statement to be hidden when includeInferred=false");
172+
checkConnection.commit();
173+
}
174+
175+
ShaclSailConnection.Settings transactionSettings = new ShaclSailConnection.Settings(false, true, false,
176+
IsolationLevels.NONE);
177+
178+
try (ConnectionsGroup connectionsGroup = new ConnectionsGroup(baseConnection, null, addedStatements, null,
179+
new Stats(), null, true, transactionSettings, true)) {
180+
StatementMatcher statementMatcher = new StatementMatcher(
181+
new StatementMatcher.Variable<>("this"),
182+
new StatementMatcher.Variable<>(P),
183+
new StatementMatcher.Variable<>(O),
184+
null,
185+
Set.of());
186+
187+
SparqlFragment query = SparqlFragment.bgp(List.of(),
188+
StatementMatcher.Variable.THIS.asSparqlVariable() + " <urn:p> <urn:o> .",
189+
false);
190+
191+
PlanNode retriever = new TargetChainRetriever(
192+
connectionsGroup,
193+
new Resource[] { null },
194+
List.of(statementMatcher),
195+
null,
196+
null,
197+
query,
198+
List.of(StatementMatcher.Variable.THIS),
199+
ConstraintComponent.Scope.nodeShape,
200+
false);
201+
202+
Assertions.assertEquals(1, countTuples(retriever),
203+
"Expected inferred statements in the delta store to be visible to target-chain retrieval");
204+
}
205+
} finally {
206+
try {
207+
addedStatements.shutDown();
208+
} finally {
209+
baseStore.shutDown();
210+
}
211+
}
212+
}
213+
214+
@Test
215+
void effectiveTargetCouldMatchShouldSeeInferredStatementsInAddedStatementsDelta() {
216+
MemoryStore baseStore = new MemoryStore();
217+
baseStore.init();
218+
219+
NotifyingSail addedStatements = new SchemaCachingRDFSInferencer(new MemoryStore(), false);
220+
addedStatements.init();
221+
222+
MemoryStore removedStatements = new MemoryStore();
223+
removedStatements.init();
224+
225+
try (SailConnection baseConnection = baseStore.getConnection()) {
226+
baseConnection.begin(IsolationLevels.NONE);
227+
228+
try (InferencerConnection addedConnection = (InferencerConnection) addedStatements.getConnection()) {
229+
addedConnection.begin(IsolationLevels.NONE);
230+
addedConnection.addInferredStatement(TARGET, P, O, (Resource) null);
231+
addedConnection.commit();
232+
}
233+
234+
try (SailConnection checkConnection = addedStatements.getConnection()) {
235+
checkConnection.begin(IsolationLevels.NONE);
236+
Assertions.assertTrue(checkConnection.hasStatement(TARGET, P, O, true, (Resource) null),
237+
"Sanity check: expected inferred statement in added-statements delta to exist");
238+
Assertions.assertFalse(checkConnection.hasStatement(TARGET, P, O, false, (Resource) null),
239+
"Sanity check: expected inferred statement to be hidden when includeInferred=false");
240+
checkConnection.commit();
241+
}
242+
243+
ShaclSailConnection.Settings transactionSettings = new ShaclSailConnection.Settings(false, true, false,
244+
IsolationLevels.NONE);
245+
246+
try (ConnectionsGroup connectionsGroup = new ConnectionsGroup(baseConnection, null, addedStatements,
247+
removedStatements,
248+
new Stats(), null, true, transactionSettings, true)) {
249+
250+
Targetable targetable = new Targetable() {
251+
@Override
252+
public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject,
253+
StatementMatcher.Variable object, RdfsSubClassOfReasoner rdfsSubClassOfReasoner,
254+
StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider,
255+
Set<String> inheritedVarNames) {
256+
StatementMatcher.Variable targetVariable = subject != null ? subject : object;
257+
StatementMatcher statementMatcher = new StatementMatcher(
258+
targetVariable,
259+
new StatementMatcher.Variable<>(P),
260+
new StatementMatcher.Variable<>(O),
261+
null,
262+
inheritedVarNames);
263+
264+
return SparqlFragment.bgp(List.of(),
265+
targetVariable.asSparqlVariable() + " <urn:p> <urn:o> .",
266+
statementMatcher);
267+
}
268+
269+
@Override
270+
public Set<Namespace> getNamespaces() {
271+
return Set.of();
272+
}
273+
};
274+
275+
ArrayDeque<Targetable> chain = new ArrayDeque<>();
276+
chain.add(targetable);
277+
278+
EffectiveTarget effectiveTarget = new EffectiveTarget(chain, null, null,
279+
new StatementMatcher.StableRandomVariableProvider());
280+
281+
Assertions.assertTrue(effectiveTarget.couldMatch(connectionsGroup, new Resource[] { null }),
282+
"Expected couldMatch() to see inferred statements in the delta store when includeInferredStatements is enabled");
283+
}
284+
} finally {
285+
try {
286+
removedStatements.shutDown();
287+
} finally {
288+
try {
289+
addedStatements.shutDown();
290+
} finally {
291+
baseStore.shutDown();
292+
}
293+
}
294+
}
295+
}
296+
110297
private static int countTuples(PlanNode planNode) {
111298
planNode.receiveLogger(ValidationExecutionLogger.getInstance(false));
112299
try (CloseableIteration<? extends ValidationTuple> iterator = planNode.iterator()) {
@@ -218,13 +405,40 @@ static TestSailContext withInferredStatement() {
218405
return new TestSailContext(sail, connection);
219406
}
220407

408+
static TestSailContext withInferredTypeFromDomain() {
409+
MemoryStore memoryStore = new MemoryStore();
410+
NotifyingSail sail = new SchemaCachingRDFSInferencer(memoryStore, false);
411+
sail.init();
412+
413+
SailConnection connection = sail.getConnection();
414+
connection.begin(IsolationLevels.NONE);
415+
connection.addStatement(DOMAIN_P, RDFS.DOMAIN, C);
416+
connection.addStatement(TARGET, DOMAIN_P, O);
417+
connection.commit();
418+
419+
connection.begin(IsolationLevels.NONE);
420+
Assertions.assertTrue(connection.hasStatement(TARGET, RDF.TYPE, C, true),
421+
"Sanity check: expected inferred rdf:type statement to exist");
422+
Assertions.assertFalse(connection.hasStatement(TARGET, RDF.TYPE, C, false),
423+
"Sanity check: expected inferred rdf:type statement to be hidden when includeInferred=false");
424+
425+
return new TestSailContext(sail, connection);
426+
}
427+
221428
ConnectionsGroup connectionsGroup(boolean includeInferredStatements) {
222429
ShaclSailConnection.Settings transactionSettings = new ShaclSailConnection.Settings(false, true, false,
223430
IsolationLevels.NONE);
224431
return new ConnectionsGroup(connection, null, null, null, new Stats(), null, includeInferredStatements,
225432
transactionSettings, true);
226433
}
227434

435+
ConnectionsGroup connectionsGroup(boolean includeInferredStatements, RdfsSubClassOfReasoner reasoner) {
436+
ShaclSailConnection.Settings transactionSettings = new ShaclSailConnection.Settings(false, true, false,
437+
IsolationLevels.NONE);
438+
return new ConnectionsGroup(connection, null, null, null, new Stats(), () -> reasoner,
439+
includeInferredStatements, transactionSettings, true);
440+
}
441+
228442
@Override
229443
public void close() {
230444
try {

0 commit comments

Comments
 (0)