Skip to content

Commit a05a684

Browse files
committed
GH-4770 add more test cases and adjust comparison code
1 parent e5b1dd7 commit a05a684

67 files changed

Lines changed: 1185 additions & 54 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@ public static List<IRI> getSupportedShaclPredicates() {
333333
SHACL.NAMESPACE_PROP,
334334
SHACL.SEVERITY_PROP,
335335
SHACL.EQUALS,
336+
SHACL.LESS_THAN,
337+
SHACL.LESS_THAN_OR_EQUALS,
336338
DASH.hasValueIn,
337339
RSX.targetShape,
338340
RSX.dataGraph,

core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java

Lines changed: 145 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher;
2727
import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach;
2828
import org.eclipse.rdf4j.sail.shacl.ast.paths.Path;
29+
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.EmptyNode;
2930
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode;
3031
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeProvider;
3132
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ShiftToPropertyShape;
@@ -135,73 +136,169 @@ private PlanNode getAllTargetsBasedOnPredicate(ConnectionsGroup connectionsGroup
135136
return Unique.getInstance(UnionNode.getInstance(targetFilter1, targetFilter2), false);
136137
}
137138

139+
// @Override
140+
// public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope,
141+
// StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) {
142+
// assert scope == Scope.propertyShape;
143+
//
144+
// PlanNode allTargetsPlan = getTargetChain()
145+
// .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
146+
// stableRandomVariableProvider)
147+
// .getPlanNode(connectionsGroup, dataGraph, Scope.nodeShape, true, null);
148+
//
149+
// allTargetsPlan = new ShiftToPropertyShape(allTargetsPlan);
150+
//
151+
// // removed statements that match predicate could affect sh:or
152+
// if (connectionsGroup.getStats().hasRemoved()) {
153+
// PlanNode deletedPredicates = new UnorderedSelect(connectionsGroup.getRemovedStatements(), null, predicate,
154+
// null, dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.propertyShape));
155+
// deletedPredicates = getTargetChain()
156+
// .getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
157+
// stableRandomVariableProvider)
158+
// .getTargetFilter(connectionsGroup, dataGraph, deletedPredicates);
159+
// deletedPredicates = getTargetChain()
160+
// .getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
161+
// stableRandomVariableProvider)
162+
// .extend(deletedPredicates, connectionsGroup, dataGraph, Scope.propertyShape, EffectiveTarget.Extend.left,
163+
// false,
164+
// null);
165+
// allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, deletedPredicates);
166+
// }
167+
//
168+
// // added statements that match predicate could affect sh:not
169+
// if (connectionsGroup.getStats().hasAdded()) {
170+
// PlanNode addedPredicates = new UnorderedSelect(connectionsGroup.getAddedStatements(), null, predicate,
171+
// null, dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.propertyShape));
172+
// addedPredicates = getTargetChain()
173+
// .getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
174+
// stableRandomVariableProvider)
175+
// .getTargetFilter(connectionsGroup, dataGraph, addedPredicates);
176+
// addedPredicates = getTargetChain()
177+
// .getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
178+
// stableRandomVariableProvider)
179+
// .extend(addedPredicates, connectionsGroup, dataGraph, Scope.propertyShape, EffectiveTarget.Extend.left,
180+
// false,
181+
// null);
182+
// allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, addedPredicates);
183+
// }
184+
//
185+
// return Unique.getInstance(new TrimToTarget(allTargetsPlan), false);
186+
// }
187+
138188
@Override
139189
public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope,
140190
StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) {
141-
assert scope == Scope.propertyShape;
191+
if (scope == Scope.propertyShape) {
192+
PlanNode allTargetsPlan = getTargetChain()
193+
.getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
194+
stableRandomVariableProvider)
195+
.getPlanNode(connectionsGroup, dataGraph, Scope.nodeShape, true, null);
196+
197+
allTargetsPlan = new ShiftToPropertyShape(allTargetsPlan);
198+
199+
// removed statements that match predicate could affect sh:or
200+
if (connectionsGroup.getStats().hasRemoved()) {
201+
PlanNode deletedPredicates = new UnorderedSelect(connectionsGroup.getRemovedStatements(), null,
202+
predicate,
203+
null, dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.propertyShape));
204+
deletedPredicates = getTargetChain()
205+
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
206+
stableRandomVariableProvider)
207+
.getTargetFilter(connectionsGroup, dataGraph, deletedPredicates);
208+
deletedPredicates = getTargetChain()
209+
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
210+
stableRandomVariableProvider)
211+
.extend(deletedPredicates, connectionsGroup, dataGraph, Scope.propertyShape,
212+
EffectiveTarget.Extend.left,
213+
false,
214+
null);
215+
allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, deletedPredicates);
216+
}
142217

143-
PlanNode allTargetsPlan = getTargetChain()
144-
.getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
145-
stableRandomVariableProvider)
146-
.getPlanNode(connectionsGroup, dataGraph, Scope.nodeShape, true, null);
218+
// added statements that match predicate could affect sh:not
219+
if (connectionsGroup.getStats().hasAdded()) {
220+
PlanNode addedPredicates = new UnorderedSelect(connectionsGroup.getAddedStatements(), null, predicate,
221+
null, dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.propertyShape));
222+
addedPredicates = getTargetChain()
223+
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
224+
stableRandomVariableProvider)
225+
.getTargetFilter(connectionsGroup, dataGraph, addedPredicates);
226+
addedPredicates = getTargetChain()
227+
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
228+
stableRandomVariableProvider)
229+
.extend(addedPredicates, connectionsGroup, dataGraph, Scope.propertyShape,
230+
EffectiveTarget.Extend.left,
231+
false,
232+
null);
233+
allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, addedPredicates);
234+
}
147235

148-
allTargetsPlan = new ShiftToPropertyShape(allTargetsPlan);
236+
return Unique.getInstance(new TrimToTarget(allTargetsPlan), false);
237+
} else {
238+
assert scope == Scope.nodeShape;
239+
240+
PlanNode allTargetsPlan = EmptyNode.getInstance();
241+
242+
// removed type statements that match clazz could affect sh:or
243+
if (connectionsGroup.getStats().hasRemoved()) {
244+
PlanNode deletedPredicates = new UnorderedSelect(connectionsGroup.getRemovedStatements(), null,
245+
predicate, null,
246+
dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.nodeShape));
247+
deletedPredicates = getTargetChain()
248+
.getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
249+
stableRandomVariableProvider)
250+
.getTargetFilter(connectionsGroup, dataGraph, deletedPredicates);
251+
deletedPredicates = getTargetChain()
252+
.getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
253+
stableRandomVariableProvider)
254+
.extend(deletedPredicates, connectionsGroup, dataGraph, Scope.nodeShape,
255+
EffectiveTarget.Extend.left,
256+
false, null);
257+
allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, deletedPredicates);
149258

150-
// removed statements that match predicate could affect sh:or
151-
if (connectionsGroup.getStats().hasRemoved()) {
152-
PlanNode deletedTypes = new UnorderedSelect(connectionsGroup.getRemovedStatements(), null, predicate,
153-
null, dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.propertyShape));
154-
deletedTypes = getTargetChain()
155-
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
156-
stableRandomVariableProvider)
157-
.getTargetFilter(connectionsGroup, dataGraph, deletedTypes);
158-
deletedTypes = getTargetChain()
159-
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
160-
stableRandomVariableProvider)
161-
.extend(deletedTypes, connectionsGroup, dataGraph, Scope.propertyShape, EffectiveTarget.Extend.left,
162-
false,
163-
null);
164-
allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, deletedTypes);
165-
}
259+
}
260+
261+
// added type statements that match clazz could affect sh:not
262+
if (connectionsGroup.getStats().hasAdded()) {
263+
PlanNode addedPredicates = new UnorderedSelect(connectionsGroup.getAddedStatements(), null, predicate,
264+
null,
265+
dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.nodeShape));
266+
addedPredicates = getTargetChain()
267+
.getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
268+
stableRandomVariableProvider)
269+
.getTargetFilter(connectionsGroup, dataGraph, addedPredicates);
270+
addedPredicates = getTargetChain()
271+
.getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
272+
stableRandomVariableProvider)
273+
.extend(addedPredicates, connectionsGroup, dataGraph, Scope.nodeShape,
274+
EffectiveTarget.Extend.left,
275+
false, null);
276+
allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, addedPredicates);
277+
278+
}
279+
280+
return Unique.getInstance(allTargetsPlan, false);
166281

167-
// added statements that match predicate could affect sh:not
168-
if (connectionsGroup.getStats().hasAdded()) {
169-
PlanNode addedTypes = new UnorderedSelect(connectionsGroup.getAddedStatements(), null, predicate,
170-
null, dataGraph, UnorderedSelect.Mapper.SubjectScopedMapper.getFunction(Scope.propertyShape));
171-
addedTypes = getTargetChain()
172-
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
173-
stableRandomVariableProvider)
174-
.getTargetFilter(connectionsGroup, dataGraph, addedTypes);
175-
addedTypes = getTargetChain()
176-
.getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(),
177-
stableRandomVariableProvider)
178-
.extend(addedTypes, connectionsGroup, dataGraph, Scope.propertyShape, EffectiveTarget.Extend.left,
179-
false,
180-
null);
181-
allTargetsPlan = UnionNode.getInstanceDedupe(allTargetsPlan, addedTypes);
182282
}
183283

184-
return Unique.getInstance(new TrimToTarget(allTargetsPlan), false);
185284
}
186285

187286
@Override
188-
public ValidationApproach getPreferredValidationApproach(ConnectionsGroup connectionsGroup) {
189-
return ValidationApproach.Transactional;
287+
public boolean requiresEvaluation(ConnectionsGroup connectionsGroup, Scope scope, Resource[] dataGraph,
288+
StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) {
289+
return super.requiresEvaluation(connectionsGroup, scope, dataGraph, stableRandomVariableProvider)
290+
|| connectionsGroup.getRemovedStatements().hasStatement(null, predicate, null, true, dataGraph)
291+
|| connectionsGroup.getAddedStatements().hasStatement(null, predicate, null, true, dataGraph);
190292
}
191293

192294
@Override
193-
public ValidationApproach getOptimalBulkValidationApproach() {
295+
public ValidationApproach getPreferredValidationApproach(ConnectionsGroup connectionsGroup) {
194296
return ValidationApproach.Transactional;
195297
}
196298

197299
@Override
198-
public boolean requiresEvaluation(ConnectionsGroup connectionsGroup, Scope scope, Resource[] dataGraph,
199-
StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) {
200-
201-
// todo both consider the target chain with added and removed values (path), and also added and removed values
202-
// for the predicate path
203-
204-
return true;
300+
public ValidationApproach getOptimalBulkValidationApproach() {
301+
return ValidationApproach.Transactional;
205302
}
206303

207304
@Override

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.eclipse.rdf4j.model.IRI;
1818
import org.eclipse.rdf4j.model.Resource;
1919
import org.eclipse.rdf4j.model.Value;
20+
import org.eclipse.rdf4j.query.algebra.Compare;
21+
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
2022
import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator;
2123
import org.eclipse.rdf4j.sail.SailConnection;
2224
import org.eclipse.rdf4j.sail.shacl.ast.Shape;
@@ -48,11 +50,11 @@ Set<Value> getInvalidValues(Set<Value> valuesByPath, Set<Value> valuesByPredicat
4850

4951
for (Value value : valuesByPath) {
5052
for (Value value1 : valuesByPredicate) {
51-
int compare = valueComparator.compare(value1, value);
52-
if (compare > 0) {
53+
boolean lessThanOrEquals = QueryEvaluationUtility.compare(value, value1, Compare.CompareOp.LE)
54+
.orElse(false);
55+
if (!lessThanOrEquals) {
5356
ret.add(value);
5457
}
55-
5658
}
5759
}
5860

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.eclipse.rdf4j.model.IRI;
1818
import org.eclipse.rdf4j.model.Resource;
1919
import org.eclipse.rdf4j.model.Value;
20+
import org.eclipse.rdf4j.query.algebra.Compare;
21+
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
2022
import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator;
2123
import org.eclipse.rdf4j.sail.SailConnection;
2224
import org.eclipse.rdf4j.sail.shacl.ast.Shape;
@@ -47,11 +49,10 @@ Set<Value> getInvalidValues(Set<Value> valuesByPath, Set<Value> valuesByPredicat
4749

4850
for (Value value : valuesByPath) {
4951
for (Value value1 : valuesByPredicate) {
50-
int compare = valueComparator.compare(value1, value);
51-
if (compare >= 0) {
52+
boolean lessThan = QueryEvaluationUtility.compare(value, value1, Compare.CompareOp.LT).orElse(false);
53+
if (!lessThan) {
5254
ret.add(value);
5355
}
54-
5556
}
5657
}
5758

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
PREFIX ex: <http://example.com/ns#>
2+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
3+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
4+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
5+
PREFIX sh: <http://www.w3.org/ns/shacl#>
6+
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
7+
8+
INSERT DATA {
9+
ex:validPerson1 a ex:Person ;
10+
ex:largerOrEqual 4;
11+
ex:smallerOrEqual 4.
12+
}
13+
14+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@prefix ex: <http://example.com/ns#> .
2+
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
3+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
4+
@prefix sh: <http://www.w3.org/ns/shacl#> .
5+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
6+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
7+
@prefix rsx: <http://rdf4j.org/shacl-extensions#> .
8+
@prefix rdf4j: <http://rdf4j.org/schema/rdf4j#> .
9+
10+
[] a sh:ValidationReport;
11+
rdf4j:truncated false;
12+
sh:conforms false;
13+
sh:result [ a sh:ValidationResult;
14+
rsx:actualPairwisePath ex:smallerOrEqual;
15+
rsx:shapesGraph rdf4j:SHACLShapeGraph;
16+
sh:focusNode ex:validPerson1;
17+
sh:resultPath ex:smallerOrEqual;
18+
sh:resultSeverity sh:Violation;
19+
sh:sourceConstraintComponent sh:LessThanConstraintComponent;
20+
sh:sourceShape [ a sh:PropertyShape;
21+
sh:lessThan ex:largerOrEqual;
22+
sh:path ex:smallerOrEqual
23+
];
24+
sh:value 4
25+
] .
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
PREFIX ex: <http://example.com/ns#>
2+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
3+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
4+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
5+
PREFIX sh: <http://www.w3.org/ns/shacl#>
6+
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
7+
8+
INSERT DATA {
9+
ex:validPerson1 a ex:Person ;
10+
ex:largerOrEqual "2010-01-10T00:00:01Z"^^xsd:dateTime ;
11+
ex:smallerOrEqual "2010-01-10T00:00:01Z"^^xsd:dateTime .
12+
}
13+
14+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@prefix ex: <http://example.com/ns#> .
2+
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
3+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
4+
@prefix sh: <http://www.w3.org/ns/shacl#> .
5+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
6+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
7+
@prefix rsx: <http://rdf4j.org/shacl-extensions#> .
8+
@prefix rdf4j: <http://rdf4j.org/schema/rdf4j#> .
9+
10+
[] a sh:ValidationReport;
11+
rdf4j:truncated false;
12+
sh:conforms false;
13+
sh:result [ a sh:ValidationResult;
14+
rsx:actualPairwisePath ex:smallerOrEqual;
15+
rsx:shapesGraph rdf4j:SHACLShapeGraph;
16+
sh:focusNode ex:validPerson1;
17+
sh:resultPath ex:smallerOrEqual;
18+
sh:resultSeverity sh:Violation;
19+
sh:sourceConstraintComponent sh:LessThanConstraintComponent;
20+
sh:sourceShape [ a sh:PropertyShape;
21+
sh:lessThan ex:largerOrEqual;
22+
sh:path ex:smallerOrEqual
23+
];
24+
sh:value "2010-01-10T00:00:01Z"^^xsd:dateTime
25+
] .
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
PREFIX ex: <http://example.com/ns#>
2+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
3+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
4+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
5+
PREFIX sh: <http://www.w3.org/ns/shacl#>
6+
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
7+
8+
INSERT DATA {
9+
ex:validPerson1 a ex:Person ;
10+
ex:largerOrEqual 4;
11+
ex:smallerOrEqual "a".
12+
}
13+
14+

0 commit comments

Comments
 (0)