Skip to content

Commit 10eb88e

Browse files
committed
wip
1 parent 8a0f374 commit 10eb88e

29 files changed

Lines changed: 269 additions & 134 deletions

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,9 @@ private ValidationReport performValidation(List<ContextWithShape> shapes, boolea
524524
sail.isPerformanceLogging())),
525525
sail.isGlobalLogValidationExecution(), sail.isLogValidationViolations(),
526526
sail.getEffectiveValidationResultsLimitPerConstraint(), sail.isPerformanceLogging(),
527-
logger
528-
))
527+
sail.isLogValidationPlans(),
528+
logger,
529+
connectionsGroup))
529530

530531
.filter(ShapeValidationContainer::hasPlanNode)
531532
.map(validationContainer -> validationContainer::performValidation);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ private static ValidationReport performValidation(List<ContextWithShape> shapes,
115115
() -> contextWithShape.getShape()
116116
.generatePlans(connectionsGroup,
117117
new ValidationSettings(contextWithShape.getDataGraph(), false, true, false)),
118-
false, false, 1000, false, logger
119-
)
118+
false, false, 1000, false, false, logger,
119+
connectionsGroup)
120120
)
121121
.filter(ShapeValidationContainer::hasPlanNode)
122122
.map(ShapeValidationContainer::performValidation)

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

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,22 @@
1111

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

14+
import java.util.Arrays;
1415
import java.util.List;
1516
import java.util.function.Supplier;
1617
import java.util.stream.Collectors;
1718

19+
import org.apache.commons.text.StringEscapeUtils;
1820
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
21+
import org.eclipse.rdf4j.sail.SailConnection;
1922
import org.eclipse.rdf4j.sail.SailException;
2023
import org.eclipse.rdf4j.sail.shacl.ast.Shape;
2124
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode;
2225
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.SingleCloseablePlanNode;
2326
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ValidationExecutionLogger;
2427
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ValidationTuple;
2528
import org.eclipse.rdf4j.sail.shacl.results.lazy.ValidationResultIterator;
29+
import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup;
2630
import org.slf4j.Logger;
2731

2832
class ShapeValidationContainer {
@@ -36,14 +40,64 @@ class ShapeValidationContainer {
3640

3741
public ShapeValidationContainer(Shape shape, Supplier<PlanNode> planNodeSupplier, boolean logValidationExecution,
3842
boolean logValidationViolations, long effectiveValidationResultsLimitPerConstraint,
39-
boolean performanceLogging, Logger logger) {
43+
boolean performanceLogging, boolean logValidationPlans, Logger logger, ConnectionsGroup connectionsGroup) {
4044
this.shape = shape;
4145
this.logValidationViolations = logValidationViolations;
4246
this.effectiveValidationResultsLimitPerConstraint = effectiveValidationResultsLimitPerConstraint;
4347
this.performanceLogging = performanceLogging;
4448
this.logger = logger;
4549
try {
4650
PlanNode planNode = planNodeSupplier.get();
51+
52+
if (logValidationPlans) {
53+
54+
StringBuilder planAsGraphvizDot = new StringBuilder();
55+
56+
planAsGraphvizDot.append(
57+
"rank1 [style=invisible];\n" +
58+
"rank2 [style=invisible];\n" +
59+
"\n" +
60+
"rank1 -> rank2 [color=white];\n");
61+
62+
planAsGraphvizDot.append("{\n")
63+
.append("\trank = same;\n")
64+
.append("\trank2 -> ")
65+
.append(System.identityHashCode(connectionsGroup.getBaseConnection()))
66+
.append(" -> ")
67+
.append(System.identityHashCode(connectionsGroup.getAddedStatements()))
68+
.append(" -> ")
69+
.append(System.identityHashCode(connectionsGroup.getRemovedStatements()))
70+
.append(" [ style=invis ];\n")
71+
.append("\trankdir = LR;\n")
72+
.append("}\n");
73+
74+
planAsGraphvizDot.append(System.identityHashCode(connectionsGroup.getBaseConnection()))
75+
.append(" [label=\"")
76+
.append("BaseConnection")
77+
.append("\" fillcolor=\"#CACADB\", style=filled];")
78+
.append("\n");
79+
80+
planAsGraphvizDot.append(System.identityHashCode(connectionsGroup.getAddedStatements()))
81+
.append(" [label=\"")
82+
.append("AddedStatements")
83+
.append("\" fillcolor=\"#CEDBCA\", style=filled];")
84+
.append("\n");
85+
86+
planAsGraphvizDot.append(System.identityHashCode(connectionsGroup.getRemovedStatements()))
87+
.append(" [label=\"")
88+
.append("RemovedStatements")
89+
.append("\" fillcolor=\"#DBCFC9r\", style=filled];")
90+
.append("\n");
91+
92+
planNode.getPlanAsGraphvizDot(planAsGraphvizDot);
93+
94+
String[] split = planAsGraphvizDot.toString().split("\n");
95+
planAsGraphvizDot = new StringBuilder();
96+
Arrays.stream(split).map(s -> "\t" + s + "\n").forEach(planAsGraphvizDot::append);
97+
98+
logger.info("Plan as Graphviz dot:\ndigraph G {\n{}}", planAsGraphvizDot);
99+
}
100+
47101
this.validationExecutionLogger = ValidationExecutionLogger
48102
.getInstance(logValidationExecution);
49103
if (!(planNode.isGuaranteedEmpty())) {
@@ -113,7 +167,6 @@ private void handlePostLogging(long before, ValidationResultIterator validationR
113167
}
114168

115169
if (validationResults != null) {
116-
117170
if (performanceLogging) {
118171
long after = System.currentTimeMillis();
119172
logger.info("Execution of plan took {} ms for:\n{}\n",

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ static PlanNode getAllTargetsIncludingThoseAddedByPath(ConnectionsGroup connecti
155155
ValidationSettings validationSettings, Scope scope, EffectiveTarget effectiveTarget, Path path,
156156
boolean includeTargetsAffectedByRemoval) {
157157
PlanNode allTargets;
158-
BufferedSplitter addedTargets = new BufferedSplitter(
158+
BufferedSplitter addedTargets = BufferedSplitter.getInstance(
159159
effectiveTarget.getPlanNode(connectionsGroup, validationSettings.getDataGraph(),
160160
scope, includeTargetsAffectedByRemoval, null));
161161

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections
112112
}
113113

114114
} else {
115-
BufferedSplitter addedTargetsBufferedSplitter = new BufferedSplitter(
115+
BufferedSplitter addedTargetsBufferedSplitter = BufferedSplitter.getInstance(
116116
effectiveTarget.getPlanNode(connectionsGroup, validationSettings.getDataGraph(), scope, false,
117117
null));
118118
addedTargets = addedTargetsBufferedSplitter.getPlanNode();

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections
139139
false, null);
140140
} else {
141141

142-
BufferedSplitter addedTargetsBufferedSplitter = new BufferedSplitter(
142+
BufferedSplitter addedTargetsBufferedSplitter = BufferedSplitter.getInstance(
143143
effectiveTarget.getPlanNode(connectionsGroup, validationSettings.getDataGraph(), scope, false,
144144
null));
145145
addedTargets = addedTargetsBufferedSplitter.getPlanNode();
@@ -336,7 +336,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[]
336336
throw new IllegalStateException();
337337
case nodeShape:
338338

339-
BufferedSplitter targets = new BufferedSplitter(
339+
BufferedSplitter targets = BufferedSplitter.getInstance(
340340
effectiveTarget.getPlanNode(connectionsGroup, dataGraph, scope, false,
341341
null));
342342
// get all subjects of all triples where the predicate is not in the allAllowedPredicates set
@@ -386,7 +386,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[]
386386
case propertyShape:
387387
Path path = getTargetChain().getPath().get();
388388

389-
BufferedSplitter addedTargetsBufferedSplitter = new BufferedSplitter(
389+
BufferedSplitter addedTargetsBufferedSplitter = BufferedSplitter.getInstance(
390390
effectiveTarget.getPlanNode(connectionsGroup, dataGraph, scope, false,
391391
null));
392392
PlanNode addedTargets = addedTargetsBufferedSplitter.getPlanNode();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections
119119
if (overrideTargetNode != null) {
120120
planNodeProvider = overrideTargetNode;
121121
} else {
122-
planNodeProvider = new BufferedSplitter(
122+
planNodeProvider = BufferedSplitter.getInstance(
123123
getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope,
124124
stableRandomVariableProvider),
125125
false);

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,13 @@ public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
323323

324324
// added/removed connections are always newly minted per plan node, so we instead need to compare the underlying
325325
// sail
326-
if (connection instanceof MemoryStoreConnection) {
327-
stringBuilder
328-
.append(System.identityHashCode(((MemoryStoreConnection) connection).getSail()) + " -> " + getId())
329-
.append("\n");
330-
} else {
331-
stringBuilder.append(System.identityHashCode(connection) + " -> " + getId()).append("\n");
332-
}
326+
// if (connection instanceof MemoryStoreConnection) {
327+
// stringBuilder
328+
// .append(System.identityHashCode(((MemoryStoreConnection) connection).getSail()) + " -> " + getId())
329+
// .append("\n");
330+
// } else {
331+
stringBuilder.append(System.identityHashCode(connection) + " -> " + getId()).append("\n");
332+
// }
333333

334334
}
335335

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,34 @@ public class BufferedSplitter implements PlanNodeProvider {
4141
private final boolean cached;
4242
private volatile List<ValidationTuple> tuplesBuffer;
4343
private long id = -1;
44+
private boolean printed;
4445

45-
public BufferedSplitter(PlanNode parent, boolean cached) {
46+
private BufferedSplitter(PlanNode parent, boolean cached) {
4647
this.parent = parent;
4748
this.cached = cached;
4849
id = idCounter.incrementAndGet();
49-
5050
}
5151

52-
public BufferedSplitter(PlanNode parent) {
52+
private BufferedSplitter(PlanNode parent) {
5353
this(parent, true);
5454
}
5555

56+
public static BufferedSplitter getInstance(PlanNode parent) {
57+
if (parent instanceof BufferedSplitterPlaneNode
58+
&& ((BufferedSplitterPlaneNode) parent).bufferedSplitter.cached == true) {
59+
return ((BufferedSplitterPlaneNode) parent).bufferedSplitter;
60+
}
61+
return new BufferedSplitter(parent);
62+
}
63+
64+
public static BufferedSplitter getInstance(PlanNode parent, boolean cached) {
65+
if (parent instanceof BufferedSplitterPlaneNode
66+
&& ((BufferedSplitterPlaneNode) parent).bufferedSplitter.cached == cached) {
67+
return ((BufferedSplitterPlaneNode) parent).bufferedSplitter;
68+
}
69+
return new BufferedSplitter(parent, cached);
70+
}
71+
5672
private synchronized void init() {
5773
if (tuplesBuffer == null) {
5874
tuplesBuffer = new ArrayList<>();
@@ -156,10 +172,10 @@ public int depth() {
156172

157173
@Override
158174
public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
159-
if (printed) {
175+
if (bufferedSplitter.printed) {
160176
return;
161177
}
162-
printed = true;
178+
bufferedSplitter.printed = true;
163179
stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];")
164180
.append("\n");
165181
stringBuilder.append(bufferedSplitter.parent.getId() + " -> " + getId()).append("\n");
@@ -173,7 +189,7 @@ public String getId() {
173189

174190
@Override
175191
public String toString() {
176-
return "BufferedSplitter";
192+
return "BufferedSplitter" + (cached ? " (cached)" : "");
177193
}
178194

179195
@Override

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,13 @@ public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
189189

190190
// added/removed connections are always newly minted per plan node, so we instead need to compare the underlying
191191
// sail
192-
if (connection instanceof MemoryStoreConnection) {
193-
stringBuilder.append(System.identityHashCode(((MemoryStoreConnection) connection).getSail()) + " -> "
194-
+ getId() + " [label=\"right\"]").append("\n");
195-
} else {
196-
stringBuilder.append(System.identityHashCode(connection) + " -> " + getId() + " [label=\"right\"]")
197-
.append("\n");
198-
}
192+
// if (connection instanceof MemoryStoreConnection) {
193+
// stringBuilder.append(System.identityHashCode(((MemoryStoreConnection) connection).getSail()) + " -> "
194+
// + getId() + " [label=\"right\"]").append("\n");
195+
// } else {
196+
stringBuilder.append(System.identityHashCode(connection) + " -> " + getId() + " [label=\"right\"]")
197+
.append("\n");
198+
// }
199199

200200
if (skipBasedOnPreviousConnection) {
201201

0 commit comments

Comments
 (0)