refreshShapes(SailRepositoryConnection shapesRepoConnection)
- throws SailException
- {
- try (SailRepositoryConnection beforeCommitConnection = shapesRepo.getConnection()) {
- long size = beforeCommitConnection.size();
- if (size > 0) {
- // Our inferencer both adds and removes statements.
- // To support updates I recommend having two graphs, one raw one with the unmodified data.
- // Then copy all that data into a new graph, run inferencing on that graph and use it to generate the java objects
- throw new IllegalStateException(
+ throws SailException {
+ if (!initializing) {
+ try (SailRepositoryConnection beforeCommitConnection = shapesRepo.getConnection()) {
+ boolean empty = !beforeCommitConnection.hasStatement(null, null, null, false);
+ if (!empty) {
+ // Our inferencer both adds and removes statements.
+ // To support updates I recommend having two graphs, one raw one with the unmodified data.
+ // Then copy all that data into a new graph, run inferencing on that graph and use it to generate the java objects
+ throw new IllegalStateException(
"ShaclSail does not support modifying shapes that are already loaded or loading more shapes");
+ }
}
}
@@ -293,8 +290,12 @@ public void shutDown() throws SailException {
@Override
public NotifyingSailConnection getConnection() throws SailException {
- return new ShaclSailConnection(this, super.getConnection(), super.getConnection(),
- shapesRepo.getConnection());
+ return new ShaclSailConnection(
+ this,
+ super.getConnection(),
+ super.getConnection(),
+ shapesRepo.getConnection()
+ );
}
/**
@@ -313,7 +314,7 @@ public void enableValidation() {
/**
* Check if SHACL validation on commit() is enabled.
- *
+ *
* @return true
if validation is enabled, false
otherwise.
*/
public boolean isValidationEnabled() {
@@ -322,7 +323,7 @@ public boolean isValidationEnabled() {
/**
* Check if logging of validation plans is enabled.
- *
+ *
* @return true
if validation plan logging is enabled, false
otherwise.
*/
public boolean isLogValidationPlans() {
@@ -335,7 +336,7 @@ public boolean isIgnoreNoShapesLoadedException() {
/**
* Check if shapes have been loaded into the shapes graph before other data is added
- *
+ *
* @param ignoreNoShapesLoadedException
*/
public void setIgnoreNoShapesLoadedException(boolean ignoreNoShapesLoadedException) {
@@ -345,7 +346,7 @@ public void setIgnoreNoShapesLoadedException(boolean ignoreNoShapesLoadedExcepti
/**
* Log (INFO) the executed validation plans as GraphViz DOT Recommended to disable parallel validation
* with setParallelValidation(false)
- *
+ *
* @param logValidationPlans
*/
public void setLogValidationPlans(boolean logValidationPlans) {
@@ -375,7 +376,7 @@ private void runInferencingSparqlQueries(SailRepositoryConnection shaclSailConne
/**
* Log (INFO) every execution step of the SHACL validation. This is fairly costly and should not be used
* in production. Recommended to disable parallel validation with setParallelValidation(false)
- *
+ *
* @param loggingEnabled
*/
public void setGlobalLogValidationExecution(boolean loggingEnabled) {
@@ -384,7 +385,7 @@ public void setGlobalLogValidationExecution(boolean loggingEnabled) {
/**
* Check if logging of every execution steps is enabled.
- *
+ *
* @return true
if enabled, false
otherwise.
* @see #setGlobalLogValidationExecution(boolean)
*/
@@ -395,7 +396,7 @@ public boolean isGlobalLogValidationExecution() {
/**
* Check if logging a list of violations and the triples that caused the violations is enabled. It is
* recommended to disable parallel validation with {@link #setParallelValidation(boolean)}
- *
+ *
* @see #setLogValidationViolations(boolean)
*/
public boolean isLogValidationViolations() {
@@ -405,7 +406,7 @@ public boolean isLogValidationViolations() {
/**
* Log (INFO) a list of violations and the triples that caused the violations (BETA). Recommended to
* disable parallel validation with setParallelValidation(false)
- *
+ *
* @param logValidationViolations
*/
public void setLogValidationViolations(boolean logValidationViolations) {
@@ -416,7 +417,7 @@ public void setLogValidationViolations(boolean logValidationViolations) {
* If no target is defined for a NodeShape, that NodeShape will be ignored. Calling this method with
* "true" will make such NodeShapes wildcard shapes and validate all subjects. Equivalent to setting
* sh:targetClass to owl:Thing or rdfs:Resource in an environment with a reasoner.
- *
+ *
* @param undefinedTargetValidatesAllSubjects
* default false
*/
@@ -426,7 +427,7 @@ public void setUndefinedTargetValidatesAllSubjects(boolean undefinedTargetValida
/**
* Check if {@link NodeShape}s without a defined target are considered wildcards.
- *
+ *
* @return true
if enabled, false
otherwise
* @see #setUndefinedTargetValidatesAllSubjects(boolean)
*/
@@ -436,7 +437,7 @@ public boolean isUndefinedTargetValidatesAllSubjects() {
/**
* Check if SHACL validation is run in parellel.
- *
+ *
* @return true
if enabled, false
otherwise.
*/
public boolean isParallelValidation() {
@@ -444,18 +445,23 @@ public boolean isParallelValidation() {
}
/**
- * Run SHACL validation in parallel. Default: true
- *
+ * EXPERIMENTAL! Run SHACL validation in parallel. Default: false
+ *
+ * May cause deadlock, especially when using NativeStore.
+ *
* @param parallelValidation
- * default true
- */
+ * default false
+ */
public void setParallelValidation(boolean parallelValidation) {
+ if(parallelValidation){
+ logger.warn("Parallel SHACL validation enabled. This is an experimental feature and may cause deadlocks!");
+ }
this.parallelValidation = parallelValidation;
}
/**
* Check if selected nodes caches is enabled.
- *
+ *
* @return true
if enabled, false
otherwise.
* @see #setCacheSelectNodes(boolean)
*/
@@ -467,10 +473,10 @@ public boolean isCacheSelectNodes() {
* The ShaclSail retries a lot of its relevant data through running SPARQL Select queries against the
* underlying sail and against the changes in the transaction. This is usually good for performance, but
* while validating large amounts of data disabling this cache will use less memory. Default: true
- *
+ *
* @param cacheSelectNodes
* default true
- */
+ */
public void setCacheSelectNodes(boolean cacheSelectNodes) {
this.cacheSelectNodes = cacheSelectNodes;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java
index 48187d009..7f3169ade 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java
@@ -373,33 +373,35 @@ synchronized public void close() throws SailException {
@Override
public void prepare() throws SailException {
- preparedHasRun = true;
- super.prepare();
- previousStateConnection.prepare();
+ try {
+ preparedHasRun = true;
- List nodeShapes = refreshShapes(shapesConnection);
+ List nodeShapes = refreshShapes(shapesConnection);
- // we don't support revalidation of all data when changing the shacl shapes,
- // so no need to check if the shapes have changed
- if (addedStatementsSet.isEmpty() && removedStatementsSet.isEmpty()) {
- logger.debug("Nothing has changed, nothing to validate.");
- return;
- }
+ // we don't support revalidation of all data when changing the shacl shapes,
+ // so no need to check if the shapes have changed
+ if (addedStatementsSet.isEmpty() && removedStatementsSet.isEmpty()) {
+ logger.debug("Nothing has changed, nothing to validate.");
+ return;
+ }
- if (!sail.isIgnoreNoShapesLoadedException()
- && ((!addedStatementsSet.isEmpty() || !removedStatementsSet.isEmpty())
- && nodeShapes.isEmpty())) {
- throw new NoShapesLoadedException();
- }
+ if (!sail.isIgnoreNoShapesLoadedException()
+ && ((!addedStatementsSet.isEmpty() || !removedStatementsSet.isEmpty())
+ && nodeShapes.isEmpty())) {
+ throw new NoShapesLoadedException();
+ }
- List invalidTuples = validate();
- boolean valid = invalidTuples.isEmpty();
+ List invalidTuples = validate();
+ boolean valid = invalidTuples.isEmpty();
- if (!valid) {
- throw new ShaclSailValidationException(invalidTuples);
+ if (!valid) {
+ throw new ShaclSailValidationException(invalidTuples);
+ }
+ }finally {
+ super.prepare();
+ previousStateConnection.prepare();
}
-
}
@Override
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java
index ff571c324..07c366d35 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java
@@ -34,7 +34,7 @@
*/
public class ShaclSailConfig extends AbstractDelegatingSailImplConfig {
- public static final boolean PARALLEL_VALIDATION_DEFAULT = true;
+ public static final boolean PARALLEL_VALIDATION_DEFAULT = false;
public static final boolean UNDEFINED_TARGET_VALIDATES_ALL_SUBJECTS_DEFAULT = false;
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BufferedPlanNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BufferedPlanNode.java
new file mode 100644
index 000000000..67a7b8232
--- /dev/null
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BufferedPlanNode.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
+package org.eclipse.rdf4j.sail.shacl.planNodes;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.eclipse.rdf4j.common.iteration.CloseableIteration;
+import org.eclipse.rdf4j.sail.SailException;
+
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+public class BufferedPlanNode implements PushablePlanNode {
+
+ private T parent;
+
+ private Queue buffer = new ArrayDeque<>();
+ private boolean closed;
+ private boolean printed;
+
+
+ BufferedPlanNode(T parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public CloseableIteration iterator() {
+ return new CloseableIteration() {
+
+ {
+ parent.init();
+ }
+
+ @Override
+ public void close() throws SailException {
+ closed = true;
+ parent.close();
+ }
+
+ @Override
+ public boolean hasNext() throws SailException {
+ calculateNext();
+ return !buffer.isEmpty();
+ }
+
+ private void calculateNext() {
+ while (buffer.isEmpty()) {
+ boolean success = parent.incrementIterator();
+ if (!success) {
+ break;
+ }
+ }
+ }
+
+ @Override
+ public Tuple next() throws SailException {
+ calculateNext();
+ return buffer.remove();
+ }
+
+ @Override
+ public void remove() throws SailException {
+
+ }
+ };
+ }
+
+ @Override
+ public int depth() {
+ return parent.depth();
+ }
+
+ @Override
+ public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
+ if (printed) {
+ return;
+ }
+ printed = true;
+ parent.getPlanAsGraphvizDot(stringBuilder);
+
+ stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];").append("\n");
+ }
+
+ @Override
+ public String getId() {
+ return System.identityHashCode(this) + "";
+ }
+
+ @Override
+ public IteratorData getIteratorDataType() {
+ return parent.getIteratorDataType();
+ }
+
+ @Override
+ public void push(Tuple next) {
+ buffer.add(next);
+ }
+
+ @Override
+ public boolean isClosed() {
+ return closed;
+ }
+
+ @Override
+ public String toString() {
+ return "BufferedPlanNode";
+ }
+}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BufferedTupleFromFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BufferedTupleFromFilter.java
deleted file mode 100644
index a596d2f98..000000000
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BufferedTupleFromFilter.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2018 Eclipse RDF4J contributors.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Distribution License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *******************************************************************************/
-
-package org.eclipse.rdf4j.sail.shacl.planNodes;
-
-
-import org.apache.commons.lang.StringEscapeUtils;
-import org.eclipse.rdf4j.common.iteration.CloseableIteration;
-import org.eclipse.rdf4j.sail.SailException;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-
-/**
- * @author Håvard Ottestad
- */
-public class BufferedTupleFromFilter implements PlanNode, PushBasedPlanNode, SupportsParentProvider {
-
-
- private CloseableIteration parentIterator;
-
- LinkedList next = new LinkedList<>();
- private ParentProvider parentProvider;
- private boolean printed = false;
-
- @Override
- public CloseableIteration iterator() {
- return new CloseableIteration() {
-
- private void calculateNext() {
- if (parentIterator != null) {
- while (next.isEmpty() && parentIterator.hasNext()) {
- parentIterator.next();
- }
- }
- }
-
- @Override
- public void close() throws SailException {
- if (parentIterator != null) {
- parentIterator.close();
- }
- }
-
- @Override
- public boolean hasNext() throws SailException {
- calculateNext();
- return !next.isEmpty();
- }
-
- @Override
- public Tuple next() throws SailException {
- calculateNext();
-
- return next.removeLast();
- }
-
-
- @Override
- public void remove() throws SailException {
-
- }
- };
- }
-
- @Override
- public int depth() {
- return parentProvider.parent().stream().mapToInt(PlanNode::depth).max().orElse(0)+1;
- }
-
-
- @Override
- public String getId() {
- return System.identityHashCode(this)+"";
- }
-
- @Override
- public IteratorData getIteratorDataType() {
- List collect = parentProvider.parent().stream().map(PlanNode::getIteratorDataType).distinct().collect(Collectors.toList());
- if(collect.size() == 1) return collect.get(0);
-
- throw new IllegalStateException("Not implemented");
- }
-
- @Override
- public void push(Tuple t) {
- if (t != null) {
- next.addFirst(t);
- }
- }
-
- @Override
- public void parentIterator(CloseableIteration iterator) {
- parentIterator = iterator;
- }
-
-
- @Override
- public void receiveParentProvider(ParentProvider parentProvider) {
- this.parentProvider = parentProvider;
- }
-
-
- @Override
- public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
- if(printed) return;
- printed = true;
-
- stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];").append("\n");
-
- if(parentProvider instanceof PlanNode){
- ((PlanNode) parentProvider).getPlanAsGraphvizDot(stringBuilder);
-
- }
-
- if(parentProvider instanceof FilterPlanNode){
- ((FilterPlanNode) parentProvider).getPlanAsGraphvizDot(stringBuilder);
-
- }
- }
-
- @Override
- public String toString() {
- return "BufferedTupleFromFilter";
- }
-}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/DatatypeFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/DatatypeFilter.java
index 5f2a9e7bf..66fb97617 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/DatatypeFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/DatatypeFilter.java
@@ -19,8 +19,8 @@ public class DatatypeFilter extends FilterPlanNode {
private final Resource datatype;
- public DatatypeFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, Resource datatype) {
- super(parent, trueNode, falseNode);
+ public DatatypeFilter(PlanNode parent, Resource datatype) {
+ super(parent);
this.datatype = datatype;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java
index 01a1f9357..07c5e40fd 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java
@@ -21,6 +21,7 @@ public class EnrichWithShape implements PlanNode {
private final PropertyShape propertyShape;
private final PlanNode parent;
private boolean printed = false;
+ boolean closed;
public EnrichWithShape(PlanNode parent, PropertyShape propertyShape) {
this.parent = parent;
@@ -29,6 +30,9 @@ public EnrichWithShape(PlanNode parent, PropertyShape propertyShape) {
@Override
public CloseableIteration iterator() {
+ if(closed){
+ throw new IllegalStateException();
+ }
return new CloseableIteration() {
CloseableIteration parentIterator = parent.iterator();
@@ -52,7 +56,11 @@ public void remove() throws SailException {
@Override
public void close() throws SailException {
- parentIterator.close();
+ closed = true;
+ if(parentIterator != null){
+ parentIterator.close();
+ parentIterator = null;
+ }
}
};
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java
index 334b808e9..49bae8de4 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java
@@ -1,3 +1,10 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
package org.eclipse.rdf4j.sail.shacl.planNodes;
import org.apache.commons.lang.StringEscapeUtils;
@@ -176,4 +183,11 @@ public IteratorData getIteratorDataType() {
throw new IllegalStateException("Not implemented support for when left and right have different types of data");
}
+
+ @Override
+ public String toString() {
+ return "EqualsJoin{" +
+ "useAsFilter=" + useAsFilter +
+ '}';
+ }
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/ExistsFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/ExistsFilter.java
deleted file mode 100644
index b1249dce8..000000000
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/ExistsFilter.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2018 Eclipse RDF4J contributors.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Distribution License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *******************************************************************************/
-
-package org.eclipse.rdf4j.sail.shacl.planNodes;
-
-
-/**
- * @author Håvard Ottestad
- */
-public class ExistsFilter extends FilterPlanNode {
-
- public ExistsFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode) {
- super(parent, trueNode, falseNode);
- }
-
- @Override
- boolean checkTuple(Tuple t) {
- return false;
- }
-
-}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java
index 429a9d73a..caa3cf750 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java
@@ -16,51 +16,60 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Arrays;
-import java.util.List;
-
/**
* @author Håvard Ottestad
*/
-public abstract class FilterPlanNode implements ParentProvider {
+public abstract class FilterPlanNode implements MultiStreamPlanNode, PlanNode {
static private final Logger logger = LoggerFactory.getLogger(FilterPlanNode.class);
PlanNode parent;
- T trueNode;
- T falseNode;
+ PushablePlanNode trueNode;
+ PushablePlanNode falseNode;
+
+ private CloseableIteration iterator;
abstract boolean checkTuple(Tuple t);
- public FilterPlanNode(PlanNode parent, T trueNode, T falseNode) {
+ public FilterPlanNode(PlanNode parent) {
this.parent = parent;
- this.trueNode = trueNode;
- this.falseNode = falseNode;
-
- initialize(trueNode, falseNode);
-
}
- private void initialize(T trueNode, T falseNode) {
- CloseableIteration iterator = iterator();
-
+ public PlanNode getTrueNode(Class extends PushablePlanNode> type) {
if (trueNode != null) {
- trueNode.parentIterator(iterator);
- trueNode.receiveParentProvider(this);
+ throw new IllegalStateException();
}
+ if (type == BufferedPlanNode.class) {
+ trueNode = new BufferedPlanNode<>(this);
+ } else {
+ trueNode = new UnBufferedPlanNode<>(this);
+ }
+
+ return trueNode;
+ }
+
+ public PlanNode getFalseNode(Class extends PushablePlanNode> type) {
if (falseNode != null) {
- falseNode.parentIterator(iterator);
- falseNode.receiveParentProvider(this);
+ throw new IllegalStateException();
+ }
+ if (type == BufferedPlanNode.class) {
+ falseNode = new BufferedPlanNode<>(this);
+ } else {
+ falseNode = new UnBufferedPlanNode<>(this);
+
}
+
+ return falseNode;
}
- private CloseableIteration iterator() {
- FilterPlanNode that = this;
+
+ public CloseableIteration iterator() {
+
return new CloseableIteration() {
CloseableIteration parentIterator;
@@ -68,8 +77,8 @@ private CloseableIteration iterator() {
Tuple next;
private void calculateNext() {
- if(parentIterator == null){
- parentIterator = parent.iterator();
+ if (parentIterator == null) {
+ parentIterator = parent.iterator();
}
if (next != null) {
@@ -81,16 +90,16 @@ private void calculateNext() {
if (checkTuple(temp)) {
if (trueNode != null) {
- if(LoggingNode.loggingEnabled){
- logger.info(leadingSpace() + that.getClass().getSimpleName() + ";trueNode: " + " " + temp.toString());
+ if (LoggingNode.loggingEnabled) {
+ logger.info(leadingSpace() + this.getClass().getSimpleName() + ";trueNode: " + " " + temp.toString());
}
trueNode.push(temp);
}
} else {
if (falseNode != null) {
- if(LoggingNode.loggingEnabled){
- logger.info(leadingSpace() + that.getClass().getSimpleName() + ";falseNode: " + " " + temp.toString());
+ if (LoggingNode.loggingEnabled) {
+ logger.info(leadingSpace() + this.getClass().getSimpleName() + ";falseNode: " + " " + temp.toString());
}
falseNode.push(temp);
@@ -120,9 +129,6 @@ public void close() throws SailException {
@Override
public boolean hasNext() throws SailException {
calculateNext();
- if (next == null) {
- close();
- }
return next != null;
}
@@ -140,42 +146,28 @@ public void remove() throws SailException {
};
}
- @Override
- public List parent() {
- return Arrays.asList(parent);
- }
-
boolean printed = false;
public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
- if(printed) return;
+ if (printed) {
+ return;
+ }
printed = true;
stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];").append("\n");
- stringBuilder.append(parent.getId()+" -> "+getId()).append("\n");
+ stringBuilder.append(parent.getId() + " -> " + getId()).append("\n");
if(trueNode != null){
- String id = getId(trueNode);
- stringBuilder.append(getId()+" -> "+id+ " [label=\"true values\"]").append("\n");
+ stringBuilder.append(getId()+" -> "+trueNode.getId()+ " [label=\"true values\"]").append("\n");
}
if(falseNode != null){
- String id = getId(falseNode);
- stringBuilder.append(getId()+" -> "+id+ " [label=\"false values\"]").append("\n");
+ stringBuilder.append(getId()+" -> "+falseNode.getId()+ " [label=\"false values\"]").append("\n");
}
parent.getPlanAsGraphvizDot(stringBuilder);
-
- }
-
- private String getId(T node) {
- if(node instanceof PlanNode){
- return ((PlanNode) node).getId();
- }
-
- return System.identityHashCode(node)+"";
}
@Override
@@ -184,11 +176,50 @@ public String toString() {
}
public String getId() {
- return System.identityHashCode(this)+"";
+ return System.identityHashCode(this) + "";
}
private String leadingSpace() {
- return StringUtils.leftPad("", parent.depth()+1, " ");
+ return StringUtils.leftPad("", parent.depth() + 1, " ");
+ }
+
+ @Override
+ public void init() {
+ if (iterator == null) {
+ iterator = iterator();
+ }
+ }
+
+
+ @Override
+ public void close() {
+ if (
+ (trueNode == null || trueNode.isClosed()) &&
+ (falseNode == null || falseNode.isClosed())
+ ) {
+ iterator.close();
+ iterator = null;
+ }
+
+ }
+
+ @Override
+ public boolean incrementIterator() {
+ if (iterator.hasNext()) {
+ iterator.next();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int depth() {
+ return parent.depth() + 1;
+ }
+
+ @Override
+ public IteratorData getIteratorDataType() {
+ return parent.getIteratorDataType();
}
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/InnerJoin.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/InnerJoin.java
index 58f904366..7c8796196 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/InnerJoin.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/InnerJoin.java
@@ -21,12 +21,11 @@
/**
* @author Håvard Ottestad
- *
+ *
* This inner join algorithm assumes the left iterator is unique for tuple[0], eg. no two tuples have the same value at index 0.
* The right iterator is allowed to contain duplicates.
- *
*/
-public class InnerJoin implements PlanNode, ParentProvider {
+public class InnerJoin implements MultiStreamPlanNode, PlanNode {
static private final Logger logger = LoggerFactory.getLogger(InnerJoin.class);
private boolean printed = false;
@@ -34,30 +33,67 @@ public class InnerJoin implements PlanNode, ParentProvider {
private PlanNode left;
private PlanNode right;
+ private CloseableIteration iterator;
+ private PushablePlanNode joined;
+ private PushablePlanNode discardedLeft;
+ private PushablePlanNode discardedRight;
- private PushBasedPlanNode discardedLeft;
- private PushBasedPlanNode discardedRight;
-
- public InnerJoin(PlanNode left, PlanNode right, PushBasedPlanNode discardedLeft, PushBasedPlanNode discardedRight) {
+ public InnerJoin(PlanNode left, PlanNode right) {
this.left = left;
this.right = right;
- this.discardedLeft = discardedLeft;
- this.discardedRight = discardedRight;
- if(discardedLeft instanceof SupportsParentProvider){
- ((SupportsParentProvider) discardedLeft).receiveParentProvider(this);
- }
- if(discardedRight instanceof SupportsParentProvider){
- ((SupportsParentProvider) discardedRight).receiveParentProvider(this);
- }
}
- @Override
+
public List parent() {
return Arrays.asList(left, right);
}
- @Override
+
+ public PlanNode getJoined(Class extends PushablePlanNode> type) {
+ if (joined != null) {
+ throw new IllegalStateException();
+ }
+ if (type == BufferedPlanNode.class) {
+ joined = new BufferedPlanNode<>(this);
+ } else {
+ joined = new UnBufferedPlanNode<>(this);
+
+ }
+
+ return joined;
+ }
+
+ public PlanNode getDiscardedLeft(Class extends PushablePlanNode> type) {
+ if (discardedLeft != null) {
+ throw new IllegalStateException();
+ }
+ if (type == BufferedPlanNode.class) {
+ discardedLeft = new BufferedPlanNode<>(this);
+ } else {
+ discardedLeft = new UnBufferedPlanNode<>(this);
+
+ }
+ return discardedLeft;
+ }
+
+ public PlanNode getDiscardedRight(Class extends PushablePlanNode> type) {
+ if (discardedRight != null) {
+ throw new IllegalStateException();
+ }
+ if (type == BufferedPlanNode.class) {
+ discardedRight = new BufferedPlanNode<>(this);
+ } else {
+ discardedRight = new UnBufferedPlanNode<>(this);
+
+ }
+ return discardedRight;
+ }
+
public CloseableIteration iterator() {
+ throw new IllegalStateException();
+ }
+
+ public CloseableIteration internalIterator() {
InnerJoin that = this;
return new CloseableIteration() {
@@ -86,14 +122,14 @@ void calculateNext() {
if (nextLeft == null) {
if (discardedRight != null) {
- while(nextRight != null){
- if(LoggingNode.loggingEnabled){
+ while (nextRight != null) {
+ if (LoggingNode.loggingEnabled) {
logger.info(leadingSpace() + that.getClass().getSimpleName() + ";discardedRight: " + " " + nextRight.toString());
}
discardedRight.push(nextRight);
- if(rightIterator.hasNext()){
+ if (rightIterator.hasNext()) {
nextRight = rightIterator.next();
- }else{
+ } else {
nextRight = null;
}
}
@@ -115,7 +151,7 @@ void calculateNext() {
if (compareTo < 0) {
if (discardedLeft != null) {
- if(LoggingNode.loggingEnabled){
+ if (LoggingNode.loggingEnabled) {
logger.info(leadingSpace() + that.getClass().getSimpleName() + ";discardedLeft: " + " " + nextLeft.toString());
}
discardedLeft.push(nextLeft);
@@ -128,7 +164,7 @@ void calculateNext() {
}
} else {
if (discardedRight != null) {
- if(LoggingNode.loggingEnabled){
+ if (LoggingNode.loggingEnabled) {
logger.info(leadingSpace() + that.getClass().getSimpleName() + ";discardedRight: " + " " + nextRight.toString());
}
discardedRight.push(nextRight);
@@ -177,45 +213,47 @@ public void remove() throws SailException {
};
}
- @Override
+
public int depth() {
return Math.max(left.depth(), right.depth());
}
- @Override
+
public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
- if(printed) return;
+ if (printed) {
+ return;
+ }
printed = true;
left.getPlanAsGraphvizDot(stringBuilder);
stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];").append("\n");
- stringBuilder.append(left.getId()+" -> "+getId()+ " [label=\"left\"];").append("\n");
- stringBuilder.append(right.getId()+" -> "+getId()+ " [label=\"right\"];").append("\n");
+ stringBuilder.append(left.getId() + " -> " + getId() + " [label=\"left\"];").append("\n");
+ stringBuilder.append(right.getId() + " -> " + getId() + " [label=\"right\"];").append("\n");
right.getPlanAsGraphvizDot(stringBuilder);
- if(discardedRight != null){
- if(discardedRight instanceof PlanNode){
- stringBuilder.append(getId()+" -> "+((PlanNode) discardedRight).getId()+ " [label=\"discardedRight\"];").append("\n");
- }
+ if (discardedRight != null) {
+ stringBuilder.append(getId() + " -> " + (discardedRight).getId() + " [label=\"discardedRight\"];").append("\n");
}
- if(discardedLeft != null){
- if(discardedLeft instanceof PlanNode){
- stringBuilder.append(getId()+" -> "+((PlanNode) discardedLeft).getId()+ " [label=\"discardedLeft\"];").append("\n");
- }
-
+ if (discardedLeft != null) {
+ stringBuilder.append(getId() + " -> " + (discardedLeft).getId() + " [label=\"discardedLeft\"];").append("\n");
+ }
+ if (joined != null) {
+ stringBuilder.append(getId() + " -> " + (joined).getId() + " [label=\"joined\"];").append("\n");
}
}
- @Override
+
public String getId() {
- return System.identityHashCode(this)+"";
+ return System.identityHashCode(this) + "";
}
- @Override
+
public IteratorData getIteratorDataType() {
- if(left.getIteratorDataType() == right.getIteratorDataType()) return left.getIteratorDataType();
+ if (left.getIteratorDataType() == right.getIteratorDataType()) {
+ return left.getIteratorDataType();
+ }
throw new IllegalStateException("Not implemented support for when left and right have different types of data");
@@ -229,4 +267,44 @@ public String toString() {
private String leadingSpace() {
return StringUtils.leftPad("", depth(), " ");
}
+
+ @Override
+ public void init() {
+ if (iterator == null) {
+ iterator = internalIterator();
+ }
+ }
+
+
+ @Override
+ public void close() {
+
+ if (
+ (discardedLeft == null || discardedLeft.isClosed()) &&
+ (discardedRight == null || discardedRight.isClosed()) &&
+ (joined == null || joined.isClosed())
+ ) {
+ iterator.close();
+ iterator = null;
+ }
+
+ }
+
+ @Override
+ public boolean incrementIterator() {
+
+ if (iterator.hasNext()) {
+ Tuple next = iterator.next();
+ if (joined != null) {
+ joined.push(next);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
}
+
+
+
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/IteratorData.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/IteratorData.java
index 98aefd2ae..162e1b77d 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/IteratorData.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/IteratorData.java
@@ -1,3 +1,10 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
package org.eclipse.rdf4j.sail.shacl.planNodes;
public enum IteratorData {
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java
index 275320835..ed6d6468e 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java
@@ -23,8 +23,8 @@ public class LanguageInFilter extends FilterPlanNode {
private final List languageIn;
- public LanguageInFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, List languageIn) {
- super(parent, trueNode, falseNode);
+ public LanguageInFilter(PlanNode parent, List languageIn) {
+ super(parent);
this.languageIn = languageIn;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LiteralComparatorFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LiteralComparatorFilter.java
index ad5d9cd6e..9adad0b48 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LiteralComparatorFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LiteralComparatorFilter.java
@@ -33,8 +33,8 @@ public class LiteralComparatorFilter extends FilterPlanNode {
private final boolean timeDatatype;
private final boolean dateDatatype;
- public LiteralComparatorFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, Literal compareTo, Function function) {
- super(parent, trueNode, falseNode);
+ public LiteralComparatorFilter(PlanNode parent, Literal compareTo, Function function) {
+ super(parent);
this.function = function;
this.compareTo = compareTo;
IRI datatype = compareTo.getDatatype();
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java
index 21fb831dd..2aa618cb5 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java
@@ -57,36 +57,36 @@ public CloseableIteration iterator() {
}
private CloseableIteration cachedIterator(CloseableIteration fromIterator) {
- try (Stream stream = Iterations.stream(fromIterator)) {
- List collect = stream.collect(Collectors.toList());
+ Stream stream = Iterations.stream(fromIterator);
+ List collect = stream.collect(Collectors.toList());
- return new CloseableIteration() {
+ return new CloseableIteration() {
- Iterator iterator = collect.iterator();
+ Iterator iterator = collect.iterator();
- @Override
- public void close() throws SailException {
+ @Override
+ public void close() throws SailException {
- }
+ }
- @Override
- public boolean hasNext() throws SailException {
- return iterator.hasNext();
- }
+ @Override
+ public boolean hasNext() throws SailException {
+ return iterator.hasNext();
+ }
- @Override
- public Tuple next() throws SailException {
- return iterator.next();
- }
+ @Override
+ public Tuple next() throws SailException {
+ return iterator.next();
+ }
- @Override
- public void remove() throws SailException {
+ @Override
+ public void remove() throws SailException {
+
+ }
+ };
- }
- };
- }
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxCountFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxCountFilter.java
index 24e10f7b4..565cf91ba 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxCountFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxCountFilter.java
@@ -18,8 +18,8 @@ public class MaxCountFilter extends FilterPlanNode {
private final long maxCount;
- public MaxCountFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, long maxCount) {
- super(parent, trueNode, falseNode);
+ public MaxCountFilter(PlanNode parent, long maxCount) {
+ super(parent);
this.maxCount = maxCount;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java
index ac7ddcee5..7df9b89f0 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java
@@ -19,8 +19,8 @@ public class MaxLengthFilter extends FilterPlanNode {
private final long maxLength;
- public MaxLengthFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, long maxLength) {
- super(parent, trueNode, falseNode);
+ public MaxLengthFilter(PlanNode parent, long maxLength) {
+ super(parent);
this.maxLength = maxLength;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinCountFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinCountFilter.java
index c8505ff56..dfe28ed2a 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinCountFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinCountFilter.java
@@ -19,8 +19,8 @@ public class MinCountFilter extends FilterPlanNode {
private final long minCount;
- public MinCountFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, long minCount) {
- super(parent, trueNode, falseNode);
+ public MinCountFilter(PlanNode parent, long minCount) {
+ super(parent);
this.minCount = minCount;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinExclusiveFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinExclusiveFilter.java
index 0feec4782..e76e285a9 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinExclusiveFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinExclusiveFilter.java
@@ -21,8 +21,8 @@ public class MinExclusiveFilter extends FilterPlanNode {
private final BigDecimal min;
- public MinExclusiveFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, BigDecimal min) {
- super(parent, trueNode, falseNode);
+ public MinExclusiveFilter(PlanNode parent, BigDecimal min) {
+ super(parent);
this.min = min;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java
index be7bcd6c0..645aee9b0 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java
@@ -18,8 +18,8 @@ public class MinLengthFilter extends FilterPlanNode {
private final long minLength;
- public MinLengthFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, long minLength) {
- super(parent, trueNode, falseNode);
+ public MinLengthFilter(PlanNode parent, long minLength) {
+ super(parent);
this.minLength = minLength;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/SupportsParentProvider.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MultiStreamPlanNode.java
similarity index 70%
rename from shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/SupportsParentProvider.java
rename to shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MultiStreamPlanNode.java
index 3629fc7ee..1fd13e403 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/SupportsParentProvider.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MultiStreamPlanNode.java
@@ -8,19 +8,10 @@
package org.eclipse.rdf4j.sail.shacl.planNodes;
-import java.util.List;
+public interface MultiStreamPlanNode {
+ void init();
-public interface SupportsParentProvider {
-
- void receiveParentProvider(ParentProvider parentProvider);
+ void close();
+ boolean incrementIterator();
}
-
-/**
- * @author Håvard Ottestad
- */
-interface ParentProvider {
-
- List parent();
-
-}
\ No newline at end of file
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java
index 5838b9fd6..20d2e2ed2 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java
@@ -23,8 +23,8 @@ public class NodeKindFilter extends FilterPlanNode {
private final NodeKindPropertyShape.NodeKind nodeKind;
- public NodeKindFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, NodeKindPropertyShape.NodeKind nodeKind) {
- super(parent, trueNode, falseNode);
+ public NodeKindFilter(PlanNode parent, NodeKindPropertyShape.NodeKind nodeKind) {
+ super(parent);
this.nodeKind = nodeKind;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java
index 257b4aded..39e97ff1e 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java
@@ -23,8 +23,8 @@ public class PatternFilter extends FilterPlanNode {
private final Pattern pattern;
- public PatternFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, String pattern, Optional flags) {
- super(parent, trueNode, falseNode);
+ public PatternFilter(PlanNode parent, String pattern, Optional flags) {
+ super(parent);
if (flags.isPresent()) {
int flag = 0b0;
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java
deleted file mode 100644
index 9426bfa45..000000000
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.eclipse.rdf4j.sail.shacl.planNodes;
-
-import org.apache.commons.lang.StringUtils;
-import org.eclipse.rdf4j.common.iteration.CloseableIteration;
-import org.eclipse.rdf4j.sail.SailException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-public class PushBasedLoggingNode implements SupportsParentProvider, PushBasedPlanNode, PlanNode {
-
- static private final Logger logger = LoggerFactory.getLogger(PushBasedLoggingNode.class);
-
-
- private final PushBasedPlanNode parent;
- private List parents;
-
- public PushBasedLoggingNode(PushBasedPlanNode parent) {
- this.parent = parent;
- }
-
-
- @Override
- public CloseableIteration iterator() {
- throw new IllegalStateException();
- }
-
- @Override
- public int depth() {
- return ((PlanNode)parent).depth();
- }
-
- @Override
- public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
- ((PlanNode)parent).getPlanAsGraphvizDot(stringBuilder);
- }
-
- @Override
- public String getId() {
- return ((PlanNode)parent).getId();
- }
-
- @Override
- public IteratorData getIteratorDataType() {
- return ((PlanNode)parent).getIteratorDataType();
- }
-
- @Override
- public void push(Tuple t) {
- if(LoggingNode.loggingEnabled){
- logger.info(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + t.toString());
- }
- parent.push(t);
- }
-
- @Override
- public void parentIterator(CloseableIteration iterator) {
- this.parent.parentIterator(iterator);
- }
-
- @Override
- public void receiveParentProvider(ParentProvider parentProvider) {
-
- this.parents = parentProvider.parent();
- ((SupportsParentProvider)this.parent).receiveParentProvider(parentProvider);
- }
-
- private String leadingSpace() {
- return StringUtils.leftPad("", depth(), " ");
- }
-}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedPlanNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushablePlanNode.java
similarity index 65%
rename from shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedPlanNode.java
rename to shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushablePlanNode.java
index 9b255f6e2..3b7aca17e 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedPlanNode.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushablePlanNode.java
@@ -8,17 +8,9 @@
package org.eclipse.rdf4j.sail.shacl.planNodes;
-import org.eclipse.rdf4j.common.iteration.CloseableIteration;
-import org.eclipse.rdf4j.sail.SailException;
-
-/**
- * @author Håvard Ottestad
- */
-public interface PushBasedPlanNode {
-
- void push(Tuple t);
-
- void parentIterator(CloseableIteration iterator);
+public interface PushablePlanNode extends PlanNode {
+ void push(Tuple tuple);
+ boolean isClosed();
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/SetFilterNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/SetFilterNode.java
new file mode 100644
index 000000000..b0a29ca2d
--- /dev/null
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/SetFilterNode.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
+
+package org.eclipse.rdf4j.sail.shacl.planNodes;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.eclipse.rdf4j.common.iteration.CloseableIteration;
+import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.sail.SailException;
+
+import java.util.Arrays;
+import java.util.Set;
+
+public class SetFilterNode implements PlanNode {
+
+ private Set targetNodeList;
+ private PlanNode parent;
+ private int index;
+ private boolean returnValid;
+ private boolean printed;
+
+ public SetFilterNode(Set targetNodeList, PlanNode parent, int index, boolean returnValid) {
+ this.targetNodeList = targetNodeList;
+ this.parent = parent;
+ this.index = index;
+ this.returnValid = returnValid;
+ }
+
+ @Override
+ public CloseableIteration iterator() {
+ return new CloseableIteration() {
+
+ CloseableIteration iterator = parent.iterator();
+
+ Tuple next;
+
+ private void calulateNext(){
+ while(next == null && iterator.hasNext()){
+ Tuple temp = iterator.next();
+ boolean contains = targetNodeList.contains(temp.getlist().get(index));
+ if(returnValid && contains){
+ next = temp;
+ }else if (!returnValid && !contains){
+ next = temp;
+ }
+ }
+ }
+
+ @Override
+ public void close() throws SailException {
+ iterator.close();
+ }
+
+ @Override
+ public boolean hasNext() throws SailException {
+ calulateNext();
+ return next != null;
+ }
+
+ @Override
+ public Tuple next() throws SailException {
+ calulateNext();
+
+ Tuple temp = next;
+ next = null;
+
+ return temp;
+ }
+
+ @Override
+ public void remove() throws SailException {
+
+ }
+ };
+ }
+
+ @Override
+ public int depth() {
+ return parent.depth() + 1;
+ }
+
+ @Override
+ public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
+ if (printed) {
+ return;
+ }
+ printed = true;
+ stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];").append("\n");
+ stringBuilder.append(parent.getId() + " -> " + getId()).append("\n");
+ parent.getPlanAsGraphvizDot(stringBuilder);
+ }
+
+ @Override
+ public String getId() {
+ return System.identityHashCode(this) + "";
+ }
+
+
+ @Override
+ public IteratorData getIteratorDataType() {
+ return parent.getIteratorDataType();
+ }
+
+ @Override
+ public String toString() {
+ return "SetFilterNode{" +
+ "targetNodeList=" + Arrays.toString(targetNodeList.toArray()) +
+ ", index=" + index +
+ ", returnValid=" + returnValid +
+ '}';
+ }
+}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java
index f61e205af..cea4f1536 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java
@@ -92,8 +92,7 @@ public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
@Override
public String toString() {
return "TrimTuple{" +
- "parent=" + parent +
- ", newLength=" + newLength +
+ "newLength=" + newLength +
", startIndex=" + startIndex +
'}';
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleLengthFilter.java
index 45c065858..ac8b3f1fb 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleLengthFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleLengthFilter.java
@@ -13,8 +13,8 @@ public class TupleLengthFilter extends FilterPlanNode{
private final boolean exact;
- public TupleLengthFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, int length, boolean exact) {
- super(parent, trueNode, falseNode);
+ public TupleLengthFilter(PlanNode parent, int length, boolean exact) {
+ super(parent);
this.length = length;
this.exact = exact;
}
diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/DirectTupleFromFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/UnBufferedPlanNode.java
similarity index 54%
rename from shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/DirectTupleFromFilter.java
rename to shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/UnBufferedPlanNode.java
index d082e110c..22f3200c1 100644
--- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/DirectTupleFromFilter.java
+++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/UnBufferedPlanNode.java
@@ -8,39 +8,37 @@
package org.eclipse.rdf4j.sail.shacl.planNodes;
-
import org.apache.commons.lang.StringEscapeUtils;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.sail.SailException;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @author Håvard Ottestad
- */
-public class DirectTupleFromFilter implements PlanNode, PushBasedPlanNode, SupportsParentProvider {
+public class UnBufferedPlanNode implements PushablePlanNode {
- private boolean printed = false;
+ private T parent;
- private CloseableIteration parentIterator;
+ Tuple next;
+ private boolean closed;
+ private boolean printed;
- Tuple next = null;
- private ParentProvider parentProvider;
+ UnBufferedPlanNode(T parent) {
+ this.parent = parent;
+ }
@Override
public CloseableIteration iterator() {
+ next = null;
+ closed = false;
+
return new CloseableIteration() {
- private void calculateNext() {
- while (next == null && parentIterator.hasNext()) {
- parentIterator.next();
- }
+ {
+ parent.init();
}
@Override
public void close() throws SailException {
- parentIterator.close();
+ closed = true;
+ parent.close();
}
@Override
@@ -49,16 +47,21 @@ public boolean hasNext() throws SailException {
return next != null;
}
+ private void calculateNext() {
+ while(next == null){
+ boolean success = parent.incrementIterator();
+ if(!success) break;
+ }
+ }
+
@Override
public Tuple next() throws SailException {
calculateNext();
Tuple temp = next;
next = null;
-
return temp;
}
-
@Override
public void remove() throws SailException {
@@ -68,57 +71,41 @@ public void remove() throws SailException {
@Override
public int depth() {
- return parentProvider.parent().stream().mapToInt(PlanNode::depth).sum()+2;
+ return parent.depth();
}
@Override
public void getPlanAsGraphvizDot(StringBuilder stringBuilder) {
- if(printed) return;
- printed = true;
- stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];").append("\n");
-
- if(parentProvider instanceof PlanNode){
- ((PlanNode) parentProvider).getPlanAsGraphvizDot(stringBuilder);
-
+ if (printed) {
+ return;
}
+ printed = true;
+ parent.getPlanAsGraphvizDot(stringBuilder);
- if(parentProvider instanceof FilterPlanNode){
- ((FilterPlanNode) parentProvider).getPlanAsGraphvizDot(stringBuilder);
-
- }
- }
-
- @Override
- public String toString() {
- return "DirectTupleFromFilter";
+ stringBuilder.append(getId() + " [label=\"" + StringEscapeUtils.escapeJava(this.toString()) + "\"];").append("\n");
}
@Override
public String getId() {
- return System.identityHashCode(this)+"";
+ return System.identityHashCode(this) + "";
}
-
@Override
public IteratorData getIteratorDataType() {
- List collect = parentProvider.parent().stream().map(PlanNode::getIteratorDataType).distinct().collect(Collectors.toList());
- if(collect.size() == 1) return collect.get(0);
-
- throw new IllegalStateException("Not implemented yet");
+ return parent.getIteratorDataType();
}
@Override
- public void push(Tuple t) {
- next = t;
+ public void push(Tuple next) {
+ this.next = next;
}
@Override
- public void parentIterator(CloseableIteration iterator) {
- parentIterator = iterator;
+ public boolean isClosed() {
+ return closed;
}
-
@Override
- public void receiveParentProvider(ParentProvider parentProvider) {
- this.parentProvider = parentProvider;
+ public String toString() {
+ return "UnBufferedPlanNode";
}
}
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java
index 56c1c0e98..2eb53baf4 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java
@@ -48,12 +48,15 @@ abstract public class AbstractShaclTest {
"test-cases/languageIn/simple",
"test-cases/nodeKind/simple",
"test-cases/minCount/simple",
+ "test-cases/minCount/targetNode",
"test-cases/maxCount/simple",
+ "test-cases/maxCount/targetNode",
"test-cases/or/inheritance",
"test-cases/or/inheritance-deep",
"test-cases/or/inheritance-deep-minCountMaxCount",
"test-cases/or/inheritanceNodeShape",
"test-cases/or/datatype",
+ "test-cases/or/datatypeTargetNode",
"test-cases/or/minCountMaxCount",
"test-cases/or/maxCount",
"test-cases/or/minCount",
@@ -68,9 +71,12 @@ abstract public class AbstractShaclTest {
"test-cases/implicitTargetClass/simple",
"test-cases/class/simple",
"test-cases/class/subclass",
+ "test-cases/class/targetNode",
"test-cases/or/class",
"test-cases/or/datatype2",
- "test-cases/or/minCountDifferentPath"
+ "test-cases/or/minCountDifferentPath",
+ "test-cases/datatype/targetNode"
+
);
final String testCasePath;
@@ -147,6 +153,7 @@ static void runTestCase(String shaclPath, String dataPath, ExpectedResult expect
System.out.println(shaclFile);
ShaclSail shaclSail = new ShaclSail(new MemoryStore());
shaclSail.setLogValidationPlans(true);
+// shaclSail.setParallelValidation(false);
SailRepository shaclRepository = new SailRepository(shaclSail);
shaclRepository.init();
Utils.loadShapeData(shaclRepository, shaclFile);
@@ -220,6 +227,7 @@ static void runTestCaseSingleTransaction(String shaclPath, String dataPath, Expe
ShaclSail shaclSail = new ShaclSail(new MemoryStore());
SailRepository shaclRepository = new SailRepository(shaclSail);
+ shaclSail.setLogValidationPlans(true);
shaclRepository.init();
Utils.loadShapeData(shaclRepository, shaclPath + "shacl.ttl");
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/DeadlockTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/DeadlockTest.java
new file mode 100644
index 000000000..e72097625
--- /dev/null
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/DeadlockTest.java
@@ -0,0 +1,47 @@
+package org.eclipse.rdf4j.sail.shacl;
+
+import org.assertj.core.util.Files;
+import org.eclipse.rdf4j.IsolationLevels;
+import org.eclipse.rdf4j.common.io.IOUtil;
+import org.eclipse.rdf4j.repository.sail.SailRepository;
+import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
+import org.eclipse.rdf4j.sail.nativerdf.NativeStore;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+public class DeadlockTest {
+
+ @Test
+ public void test() throws IOException {
+
+ for (int i = 0; i < 10; i++) {
+
+ String shaclPath = "complexBenchmark/";
+
+ File dataDir = Files.newTemporaryFolder();
+ dataDir.deleteOnExit();
+
+ ShaclSail shaclSail = new ShaclSail(new NativeStore(dataDir));
+ SailRepository shaclRepository = new SailRepository(shaclSail);
+ shaclRepository.init();
+
+ shaclSail.setParallelValidation(true);
+
+ Utils.loadShapeData(shaclRepository, shaclPath + "shacl.ttl");
+
+ try (SailRepositoryConnection connection = shaclRepository.getConnection()) {
+
+ connection.begin(IsolationLevels.SNAPSHOT);
+ connection.prepareUpdate(IOUtil.readString(DeadlockTest.class.getClassLoader().getResourceAsStream(shaclPath + "transaction1.qr"))).execute();
+ connection.commit();
+
+ connection.begin(IsolationLevels.SNAPSHOT);
+ connection.prepareUpdate(IOUtil.readString(DeadlockTest.class.getClassLoader().getResourceAsStream(shaclPath + "transaction2.qr"))).execute();
+ connection.commit();
+ }
+ }
+ }
+
+}
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/InnerJoinTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/InnerJoinTest.java
index a846b2463..113c0d9b5 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/InnerJoinTest.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/InnerJoinTest.java
@@ -12,6 +12,7 @@
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.sail.shacl.mock.MockConsumePlanNode;
import org.eclipse.rdf4j.sail.shacl.mock.MockInputPlanNode;
+import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedPlanNode;
import org.eclipse.rdf4j.sail.shacl.planNodes.InnerJoin;
import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode;
import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode;
@@ -42,7 +43,7 @@ public void testSimple() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a", "b"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -60,7 +61,7 @@ public void testSimple2() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a1", "b"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -78,7 +79,7 @@ public void testSimple3() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a2", "b"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -96,7 +97,7 @@ public void testSimple4() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"));
PlanNode right = new MockInputPlanNode(Arrays.asList());
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -114,7 +115,7 @@ public void testSimple5() {
PlanNode left = new MockInputPlanNode();
PlanNode right = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -131,7 +132,7 @@ public void testSimple6() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"), Arrays.asList("a3"), Arrays.asList("a4"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a1", "b1"), Arrays.asList("a2", "b2"), Arrays.asList("a3", "b3"), Arrays.asList("a4", "b4"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -148,7 +149,7 @@ public void testSimple7() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a1", "b1"), Arrays.asList("a2", "b2"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -165,7 +166,7 @@ public void testSimple8() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"), Arrays.asList("a3"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a1", "b1"), Arrays.asList("a2", "b2"), Arrays.asList("a3", "b3"));
- PlanNode innerJoin = new LoggingNode(new InnerJoin(left, right, null, null), "");
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -182,7 +183,7 @@ public void testSimple9() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"), Arrays.asList("a3"), Arrays.asList("a4"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a1", "b1"), Arrays.asList("a2", "b2"), Arrays.asList("a2", "b22"), Arrays.asList("a3", "b3"), Arrays.asList("a4", "b4"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -199,7 +200,7 @@ public void testSimple10() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"), Arrays.asList("a3"), Arrays.asList("a4"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a1", "b1"), Arrays.asList("a2", "b2"), Arrays.asList("a2", "b22"), Arrays.asList("a4", "b4"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -217,7 +218,7 @@ public void testSimple11() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"), Arrays.asList("a3"), Arrays.asList("a4"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a2", "b2"), Arrays.asList("a2", "b22"), Arrays.asList("a4", "b4"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -234,7 +235,7 @@ public void testSimple12() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"), Arrays.asList("a3"), Arrays.asList("a4"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a2", "b2"), Arrays.asList("a2", "b22"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
@@ -252,7 +253,7 @@ public void testSimple13() {
PlanNode left = new MockInputPlanNode(Arrays.asList("a1"), Arrays.asList("a2"), Arrays.asList("a3"), Arrays.asList("a4"));
PlanNode right = new MockInputPlanNode(Arrays.asList("a1", "b1"), Arrays.asList("a1", "b11"), Arrays.asList("a2", "b2"), Arrays.asList("a2", "b22"));
- InnerJoin innerJoin = new InnerJoin(left, right, null, null);
+ PlanNode innerJoin = new InnerJoin(left, right).getJoined(BufferedPlanNode.class);
List tuples = new MockConsumePlanNode(innerJoin).asList();
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/NativeStoreTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/NativeStoreTest.java
new file mode 100644
index 000000000..04b7d2fd6
--- /dev/null
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/NativeStoreTest.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
+package org.eclipse.rdf4j.sail.shacl;
+
+import org.assertj.core.util.Files;
+import org.eclipse.rdf4j.model.vocabulary.RDF4J;
+import org.eclipse.rdf4j.repository.RepositoryException;
+import org.eclipse.rdf4j.repository.sail.SailRepository;
+import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
+import org.eclipse.rdf4j.rio.RDFFormat;
+import org.eclipse.rdf4j.sail.nativerdf.NativeStore;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.StringReader;
+
+public class NativeStoreTest {
+
+ @Test
+ public void testEmpty() throws IOException {
+
+ File file = Files.newTemporaryFolder();
+
+ SailRepository shaclSail = new SailRepository(new ShaclSail(new NativeStore(file)));
+ shaclSail.init();
+
+ shaclSail.shutDown();
+
+ delete(file);
+ }
+
+ @Test(expected = ShaclSailValidationException.class)
+ public void testPersistedShapes() throws Throwable {
+
+ File file = Files.newTemporaryFolder();
+
+ SailRepository shaclSail = new SailRepository(new ShaclSail(new NativeStore(file)));
+ shaclSail.init();
+ addShapes(shaclSail);
+ shaclSail.shutDown();
+
+ shaclSail = new SailRepository(new ShaclSail(new NativeStore(file)));
+ shaclSail.init();
+
+ try (SailRepositoryConnection connection = shaclSail.getConnection()) {
+
+ connection.begin();
+
+ StringReader invalidSampleData = new StringReader(
+ String.join("\n", "",
+ "@prefix ex: .",
+ "@prefix foaf: .",
+ "@prefix xsd: .",
+
+ "ex:peter a foaf:Person ;",
+ " foaf:age 20, \"30\"^^xsd:int ."
+
+ ));
+
+ connection.add(invalidSampleData, "", RDFFormat.TURTLE);
+ try {
+ connection.commit();
+ } catch (RepositoryException exception) {
+ throw exception.getCause();
+
+ }
+ }
+
+ shaclSail.shutDown();
+
+ delete(file);
+ }
+
+ private void addShapes(SailRepository shaclSail) throws IOException {
+ try (SailRepositoryConnection connection = shaclSail.getConnection()) {
+
+ connection.begin();
+
+ StringReader shaclRules = new StringReader(
+ String.join("\n", "",
+ "@prefix ex: .",
+ "@prefix sh: .",
+ "@prefix xsd: .",
+ "@prefix foaf: .",
+
+ "ex:PersonShape",
+ " a sh:NodeShape ;",
+ " sh:targetClass foaf:Person ;",
+ " sh:property ex:PersonShapeProperty .",
+
+ "ex:PersonShapeProperty ",
+ " sh:path foaf:age ;",
+ " sh:datatype xsd:int ;",
+ " sh:maxCount 1 ;",
+ " sh:minCount 1 ."
+ ));
+
+ connection.add(shaclRules, "", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
+ connection.commit();
+
+ }
+ }
+
+ void delete(File f) throws IOException {
+ if (f.isDirectory()) {
+ for (File c : f.listFiles()) {
+ delete(c);
+ }
+ }
+ if (!f.delete()) {
+ throw new FileNotFoundException("Failed to delete file: " + f);
+ }
+ }
+
+}
+
+
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/ClassBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/ClassBenchmarkEmpty.java
new file mode 100644
index 000000000..71383b9a6
--- /dev/null
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/ClassBenchmarkEmpty.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
+
+package org.eclipse.rdf4j.sail.shacl.benchmark;
+
+import ch.qos.logback.classic.Logger;
+import org.eclipse.rdf4j.common.iteration.Iterations;
+import org.eclipse.rdf4j.model.Statement;
+import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
+import org.eclipse.rdf4j.model.vocabulary.FOAF;
+import org.eclipse.rdf4j.model.vocabulary.RDF;
+import org.eclipse.rdf4j.query.BindingSet;
+import org.eclipse.rdf4j.repository.sail.SailRepository;
+import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
+import org.eclipse.rdf4j.sail.memory.MemoryStore;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
+import org.eclipse.rdf4j.sail.shacl.Utils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+/**
+ * @author Håvard Ottestad
+ */
+@State(Scope.Benchmark)
+@Warmup(iterations = 20)
+@BenchmarkMode({Mode.AverageTime})
+@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
+@Measurement(iterations = 10)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+public class ClassBenchmarkEmpty {
+
+
+ private List> allStatements;
+
+ @Setup(Level.Invocation)
+ public void setUp() {
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
+
+ allStatements = new ArrayList<>(10);
+
+
+ SimpleValueFactory vf = SimpleValueFactory.getInstance();
+
+ for (int j = 0; j < 10; j++) {
+ List statements = new ArrayList<>(101);
+ allStatements.add(statements);
+ for (int i = 0; i < 1000; i++) {
+ statements.add(
+ vf.createStatement(vf.createIRI("http://example.com/" + i + "_" + j), RDF.TYPE, FOAF.PERSON)
+ );
+ statements.add(
+ vf.createStatement(vf.createIRI("http://example.com/" + i + "_" + j), FOAF.KNOWS, vf.createIRI("http://example.com/friend" + i + "_" + j))
+ );
+ statements.add(
+ vf.createStatement(vf.createIRI("http://example.com/friend" + i + "_" + j), RDF.TYPE, FOAF.PERSON)
+ );
+ }
+ }
+ System.gc();
+
+ }
+
+ @TearDown(Level.Iteration)
+ public void tearDown() {
+ allStatements.clear();
+ }
+
+
+ @Benchmark
+ public void shacl() throws Exception {
+
+ SailRepository repository = new SailRepository(Utils.getInitializedShaclSail("shaclClassBenchmark.ttl"));
+
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin();
+ connection.commit();
+ }
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin();
+ connection.add(statements);
+ connection.commit();
+ }
+ }
+
+ }
+
+
+ @Benchmark
+ public void noShacl() {
+
+ SailRepository repository = new SailRepository(new MemoryStore());
+
+ repository.init();
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin();
+ connection.commit();
+ }
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin();
+ connection.add(statements);
+ connection.commit();
+ }
+ }
+
+ }
+
+
+ @Benchmark
+ public void sparqlInsteadOfShacl() {
+
+ SailRepository repository = new SailRepository(new MemoryStore());
+
+ repository.init();
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin();
+ connection.commit();
+ }
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin();
+ connection.add(statements);
+ try (Stream stream = Iterations.stream(connection.prepareTupleQuery("select * where {?a a <" + FOAF.PERSON + ">. ?a <" + FOAF.KNOWS + "> ?c. FILTER(NOT EXISTS{?c a <"+FOAF.PERSON+">})}").evaluate())) {
+ stream.forEach(System.out::println);
+ }
+ connection.commit();
+ }
+ }
+
+ }
+
+}
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/ComplexBenchmark.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/ComplexBenchmark.java
index c67e9dafa..280cb140b 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/ComplexBenchmark.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/ComplexBenchmark.java
@@ -45,11 +45,11 @@
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 10)
+@Warmup(iterations = 20)
@BenchmarkMode({Mode.AverageTime})
@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
//@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC", "-XX:+UnlockCommercialFeatures", "-XX:StartFlightRecording=delay=15s,duration=120s,filename=recording.jfr,settings=ProfilingAggressive.jfc", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
-@Measurement(iterations = 30)
+@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class ComplexBenchmark {
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java
index 687d8b166..0e168ce74 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java
@@ -8,15 +8,19 @@
package org.eclipse.rdf4j.sail.shacl.benchmark;
+import ch.qos.logback.classic.Logger;
import org.eclipse.rdf4j.IsolationLevels;
+import org.eclipse.rdf4j.common.iteration.Iterations;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.FOAF;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
+import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.memory.MemoryStore;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.Utils;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -30,20 +34,22 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
/**
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 10)
+@Warmup(iterations = 20)
@BenchmarkMode({Mode.AverageTime})
@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
//@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC", "-XX:+UnlockCommercialFeatures", "-XX:StartFlightRecording=delay=5s,duration=120s,filename=recording.jfr,settings=profile", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
-@Measurement(iterations = 20)
+@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class DatatypeBenchmarkEmpty {
@@ -55,6 +61,8 @@ public class DatatypeBenchmarkEmpty {
@Setup(Level.Iteration)
public void setUp() {
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
allStatements = new ArrayList<>(NUMBER_OF_TRANSACTIONS);
@@ -131,31 +139,31 @@ public void noShacl() {
repository.shutDown();
}
-//
-//
-// @Benchmark
-// public void sparqlInsteadOfShacl() {
-//
-// SailRepository repository = new SailRepository(new MemoryStore());
-//
-// repository.init();
-//
-// try (SailRepositoryConnection connection = repository.getConnection()) {
-// connection.begin(IsolationLevels.SNAPSHOT);
-// connection.commit();
-// }
-// try (SailRepositoryConnection connection = repository.getConnection()) {
-// for (List statements : allStatements) {
-// connection.begin(IsolationLevels.SNAPSHOT);
-// connection.add(statements);
-// try (Stream stream = Iterations.stream(connection.prepareTupleQuery("select * where {?a a <" + RDFS.RESOURCE + ">; <" + FOAF.AGE + "> ?age. FILTER(datatype(?age) != )}").evaluate())) {
-// stream.forEach(System.out::println);
-// }
-// connection.commit();
-// }
-// }
-//
-// }
+
+
+ @Benchmark
+ public void sparqlInsteadOfShacl() {
+
+ SailRepository repository = new SailRepository(new MemoryStore());
+
+ repository.init();
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin(IsolationLevels.SNAPSHOT);
+ connection.commit();
+ }
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin(IsolationLevels.SNAPSHOT);
+ connection.add(statements);
+ try (Stream stream = Iterations.stream(connection.prepareTupleQuery("select * where {?a a <" + RDFS.RESOURCE + ">; <" + FOAF.AGE + "> ?age. FILTER(datatype(?age) != )}").evaluate())) {
+ stream.forEach(System.out::println);
+ }
+ connection.commit();
+ }
+ }
+
+ }
}
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkLinear.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkLinear.java
index 7315d129d..587bd2d4a 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkLinear.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkLinear.java
@@ -8,6 +8,7 @@
package org.eclipse.rdf4j.sail.shacl.benchmark;
+import ch.qos.logback.classic.Logger;
import org.eclipse.rdf4j.IsolationLevels;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
@@ -16,6 +17,8 @@
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
+import org.eclipse.rdf4j.sail.memory.MemoryStore;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.Utils;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -30,6 +33,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -39,16 +43,15 @@
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 10)
+@Warmup(iterations = 20)
@BenchmarkMode({Mode.AverageTime})
-@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G", "-Xmn2G", "-XX:+UseSerialGC", "-XX:+UnlockCommercialFeatures", "-XX:StartFlightRecording=delay=5s,duration=60s,filename=recording.jfr,settings=profile", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
-//@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G"})
-@Measurement(iterations = 30)
+//@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G", "-Xmn2G", "-XX:+UseSerialGC", "-XX:+UnlockCommercialFeatures", "-XX:StartFlightRecording=delay=5s,duration=60s,filename=recording.jfr,settings=profile", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
+@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
+@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class DatatypeBenchmarkLinear {
-// @Param({"1", "10", "100"})
- @Param({"100"})
+ @Param({"1", "10", "100"})
public int NUMBER_OF_TRANSACTIONS = 10;
private static final int STATEMENTS_PER_TRANSACTION = 100;
@@ -57,6 +60,8 @@ public class DatatypeBenchmarkLinear {
@Setup(Level.Iteration)
public void setUp() {
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
allStatements = new ArrayList<>(NUMBER_OF_TRANSACTIONS);
@@ -106,26 +111,26 @@ public void shacl() throws Exception {
}
-// @Benchmark
-// public void noShacl() {
-//
-// SailRepository repository = new SailRepository(new MemoryStore());
-//
-// repository.init();
-//
-// try (SailRepositoryConnection connection = repository.getConnection()) {
-// connection.begin(IsolationLevels.SNAPSHOT);
-// connection.commit();
-// }
-// try (SailRepositoryConnection connection = repository.getConnection()) {
-// for (List statements : allStatements) {
-// connection.begin(IsolationLevels.SNAPSHOT);
-// connection.add(statements);
-// connection.commit();
-// }
-// }
-//
-// }
+ @Benchmark
+ public void noShacl() {
+
+ SailRepository repository = new SailRepository(new MemoryStore());
+
+ repository.init();
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin(IsolationLevels.SNAPSHOT);
+ connection.commit();
+ }
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin(IsolationLevels.SNAPSHOT);
+ connection.add(statements);
+ connection.commit();
+ }
+ }
+
+ }
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java
index 95c9021da..7893a5443 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java
@@ -8,6 +8,7 @@
package org.eclipse.rdf4j.sail.shacl.benchmark;
+import ch.qos.logback.classic.Logger;
import org.eclipse.rdf4j.common.iteration.Iterations;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
@@ -19,6 +20,7 @@
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.memory.MemoryStore;
import org.eclipse.rdf4j.sail.shacl.ShaclSail;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.Utils;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -32,6 +34,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -42,9 +45,9 @@
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 10)
+@Warmup(iterations = 20)
@BenchmarkMode({Mode.AverageTime})
-@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G", "-Xmn2G"})
+@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class DatatypeBenchmarkPrefilled {
@@ -52,13 +55,21 @@ public class DatatypeBenchmarkPrefilled {
private List> allStatements;
- SailRepository shaclRepo;
- SailRepository memoryStoreRepo;
- SailRepository sparqlQueryMemoryStoreRepo;
+ private SailRepository shaclRepo;
+ private SailRepository memoryStoreRepo;
+ private SailRepository sparqlQueryMemoryStoreRepo;
@Setup(Level.Invocation)
public void setUp() throws Exception {
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
+
+ if(shaclRepo != null) shaclRepo.shutDown();
+ if(memoryStoreRepo != null) memoryStoreRepo.shutDown();
+ if(sparqlQueryMemoryStoreRepo != null) sparqlQueryMemoryStoreRepo.shutDown();
+
+
allStatements = new ArrayList<>(10);
SimpleValueFactory vf = SimpleValueFactory.getInstance();
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/Main.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/Main.java
index 62f4a7822..fa94d5b53 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/Main.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/Main.java
@@ -20,16 +20,8 @@ public class Main {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
- .include("MinCount")
-// .include(MinCountBenchmark.class.getSimpleName()+".noShacl")
-
-// .include(MinCountBenchmarkPrefilled.class.getSimpleName())
-// .include(MinCountPrefilledVsEmptyBenchmark.class.getSimpleName()+"..shaclPrefilled$")
-// .include(MinCountPrefilledVsEmptyBenchmark.class.getSimpleName()+"..shaclEmpty$")
-
- .warmupIterations(10)
- .measurementIterations(10)
- .forks(1)
+ .include("")
+
//.addProfiler("stack", "lines=20;period=1;top=20")
.build();
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MaxCountBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MaxCountBenchmarkEmpty.java
new file mode 100644
index 000000000..f9b4535f5
--- /dev/null
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MaxCountBenchmarkEmpty.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
+
+package org.eclipse.rdf4j.sail.shacl.benchmark;
+
+import ch.qos.logback.classic.Logger;
+import org.eclipse.rdf4j.common.iteration.Iterations;
+import org.eclipse.rdf4j.model.Statement;
+import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
+import org.eclipse.rdf4j.model.vocabulary.RDF;
+import org.eclipse.rdf4j.model.vocabulary.RDFS;
+import org.eclipse.rdf4j.query.BindingSet;
+import org.eclipse.rdf4j.repository.sail.SailRepository;
+import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
+import org.eclipse.rdf4j.sail.memory.MemoryStore;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
+import org.eclipse.rdf4j.sail.shacl.Utils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+/**
+ * @author Håvard Ottestad
+ */
+@State(Scope.Benchmark)
+@Warmup(iterations = 20)
+@BenchmarkMode({Mode.AverageTime})
+@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
+@Measurement(iterations = 10)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+public class MaxCountBenchmarkEmpty {
+
+
+ private List> allStatements;
+
+ @Setup(Level.Invocation)
+ public void setUp() {
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
+
+ allStatements = new ArrayList<>(10);
+
+
+ SimpleValueFactory vf = SimpleValueFactory.getInstance();
+
+ for (int j = 0; j < 10; j++) {
+ List statements = new ArrayList<>(101);
+ allStatements.add(statements);
+ for (int i = 0; i < 1000; i++) {
+ statements.add(
+ vf.createStatement(vf.createIRI("http://example.com/" + i + "_" + j), RDF.TYPE, RDFS.RESOURCE)
+ );
+ statements.add(
+ vf.createStatement(vf.createIRI("http://example.com/" + i + "_" + j), RDFS.LABEL, vf.createLiteral("label" + i))
+ );
+ }
+ }
+ System.gc();
+
+ }
+
+ @TearDown(Level.Iteration)
+ public void tearDown() {
+ allStatements.clear();
+ }
+
+
+ @Benchmark
+ public void shacl() throws Exception {
+
+ SailRepository repository = new SailRepository(Utils.getInitializedShaclSail("shaclMaxCountBenchmark.ttl"));
+
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin();
+ connection.commit();
+ }
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin();
+ connection.add(statements);
+ connection.commit();
+ }
+ }
+
+ }
+
+
+ @Benchmark
+ public void noShacl() {
+
+ SailRepository repository = new SailRepository(new MemoryStore());
+
+ repository.init();
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin();
+ connection.commit();
+ }
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin();
+ connection.add(statements);
+ connection.commit();
+ }
+ }
+
+ }
+
+
+ @Benchmark
+ public void sparqlInsteadOfShacl() {
+
+ SailRepository repository = new SailRepository(new MemoryStore());
+
+ repository.init();
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin();
+ connection.commit();
+ }
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin();
+ connection.add(statements);
+ try (Stream stream = Iterations.stream(connection.prepareTupleQuery("select * where {?a a <" + RDFS.RESOURCE + ">. ?a <" + RDFS.LABEL + "> ?c, ?d. FILTER(?c != ?d)}").evaluate())) {
+ stream.forEach(System.out::println);
+ }
+ connection.commit();
+ }
+ }
+
+ }
+
+ @Benchmark
+ public void sparqlGroupByInsteadOfShacl() {
+
+ SailRepository repository = new SailRepository(new MemoryStore());
+
+ repository.init();
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin();
+ connection.commit();
+ }
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ for (List statements : allStatements) {
+ connection.begin();
+ connection.add(statements);
+ try (Stream stream = Iterations.stream(connection.prepareTupleQuery("select ?a (count(?c) as ?count) where {?a a <" + RDFS.RESOURCE + ">. ?a <" + RDFS.LABEL + "> ?c} group by ?a having(?count > 1)").evaluate())) {
+ stream.forEach(System.out::println);
+ }
+ connection.commit();
+ }
+ }
+
+ }
+
+
+
+}
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java
index dfbadaef1..99f86398e 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java
@@ -8,6 +8,7 @@
package org.eclipse.rdf4j.sail.shacl.benchmark;
+import ch.qos.logback.classic.Logger;
import org.eclipse.rdf4j.common.iteration.Iterations;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
@@ -17,6 +18,7 @@
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.memory.MemoryStore;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.Utils;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -30,6 +32,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -40,9 +43,9 @@
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 10)
+@Warmup(iterations = 20)
@BenchmarkMode({Mode.AverageTime})
-@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G", "-Xmn2G"})
+@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class MinCountBenchmarkEmpty {
@@ -52,8 +55,8 @@ public class MinCountBenchmarkEmpty {
@Setup(Level.Invocation)
public void setUp() {
-
-
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
allStatements = new ArrayList<>(10);
@@ -63,7 +66,7 @@ public void setUp() {
for (int j = 0; j < 10; j++) {
List statements = new ArrayList<>(101);
allStatements.add(statements);
- for (int i = 0; i < 100; i++) {
+ for (int i = 0; i < 1000; i++) {
statements.add(
vf.createStatement(vf.createIRI("http://example.com/" + i + "_" + j), RDF.TYPE, RDFS.RESOURCE)
);
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java
index fb058163d..2e4ab7bc7 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java
@@ -8,6 +8,7 @@
package org.eclipse.rdf4j.sail.shacl.benchmark;
+import ch.qos.logback.classic.Logger;
import org.eclipse.rdf4j.common.iteration.Iterations;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
@@ -18,6 +19,7 @@
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.memory.MemoryStore;
import org.eclipse.rdf4j.sail.shacl.ShaclSail;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.Utils;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -31,6 +33,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -41,9 +44,9 @@
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 10)
+@Warmup(iterations = 20)
@BenchmarkMode({Mode.AverageTime})
-@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G", "-Xmn2G"})
+@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class MinCountBenchmarkPrefilled {
@@ -51,13 +54,21 @@ public class MinCountBenchmarkPrefilled {
private List> allStatements;
- SailRepository shaclRepo;
- SailRepository memoryStoreRepo;
- SailRepository sparqlQueryMemoryStoreRepo;
+ private SailRepository shaclRepo;
+ private SailRepository memoryStoreRepo;
+ private SailRepository sparqlQueryMemoryStoreRepo;
@Setup(Level.Invocation)
public void setUp() throws Exception {
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
+
+ if(shaclRepo != null) shaclRepo.shutDown();
+ if(memoryStoreRepo != null) memoryStoreRepo.shutDown();
+ if(sparqlQueryMemoryStoreRepo != null) sparqlQueryMemoryStoreRepo.shutDown();
+
+
allStatements = new ArrayList<>(10);
SimpleValueFactory vf = SimpleValueFactory.getInstance();
@@ -65,7 +76,7 @@ public void setUp() throws Exception {
for (int j = 0; j < 10; j++) {
List statements = new ArrayList<>(101);
allStatements.add(statements);
- for (int i = 0; i < 100; i++) {
+ for (int i = 0; i < 1000; i++) {
statements.add(
vf.createStatement(vf.createIRI("http://example.com/" + i + "_" + j), RDF.TYPE, RDFS.RESOURCE)
);
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java
index b05676b4b..d12e3320e 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java
@@ -8,6 +8,7 @@
package org.eclipse.rdf4j.sail.shacl.benchmark;
+import ch.qos.logback.classic.Logger;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
@@ -15,6 +16,7 @@
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.shacl.ShaclSail;
+import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.Utils;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -28,6 +30,7 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -37,9 +40,9 @@
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 10)
+@Warmup(iterations = 20)
@BenchmarkMode({Mode.AverageTime})
-@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G", "-Xmn2G"})
+@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC"})
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class MinCountPrefilledVsEmptyBenchmark {
@@ -51,15 +54,19 @@ public class MinCountPrefilledVsEmptyBenchmark {
@Setup(Level.Invocation)
public void setUp() throws Exception {
+ Logger root = (Logger) LoggerFactory.getLogger(ShaclSailConnection.class.getName());
+ root.setLevel(ch.qos.logback.classic.Level.INFO);
+
allStatements = new ArrayList<>(10);
+ if(shaclRepo != null) shaclRepo.shutDown();
SimpleValueFactory vf = SimpleValueFactory.getInstance();
for (int j = 0; j < 10; j++) {
List statements = new ArrayList<>(101);
allStatements.add(statements);
- for (int i = 0; i < 100; i++) {
+ for (int i = 0; i < 1000; i++) {
statements.add(
vf.createStatement(vf.createIRI("http://example.com/" + i + "_" + j), RDF.TYPE, RDFS.RESOURCE)
);
diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfigTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfigTest.java
index 05ec23ec3..be117ce9c 100644
--- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfigTest.java
+++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfigTest.java
@@ -45,7 +45,7 @@ public void setUp() throws Exception {
@Test
public void defaultsCorrectlySet() {
- assertThat(subject.isParallelValidation()).isTrue();
+ assertThat(subject.isParallelValidation()).isFalse();
assertThat(subject.isUndefinedTargetValidatesAllSubjects()).isFalse();
assertThat(subject.isLogValidationPlans()).isFalse();
assertThat(subject.isLogValidationViolations()).isFalse();
diff --git a/shacl/src/test/resources/shaclClassBenchmark.ttl b/shacl/src/test/resources/shaclClassBenchmark.ttl
new file mode 100644
index 000000000..abd6c6faa
--- /dev/null
+++ b/shacl/src/test/resources/shaclClassBenchmark.ttl
@@ -0,0 +1,18 @@
+@base .
+@prefix ex: .
+@prefix owl: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix sh: .
+@prefix xsd: .
+@prefix foaf: .
+
+ex:PersonShape
+ a sh:NodeShape ;
+ sh:targetClass foaf:Person ;
+ sh:property ex:PersonShapeProperty .
+
+
+ex:PersonShapeProperty
+ sh:path foaf:knows ;
+ sh:class foaf:Person .
\ No newline at end of file
diff --git a/shacl/src/test/resources/shaclMaxCountBenchmark.ttl b/shacl/src/test/resources/shaclMaxCountBenchmark.ttl
new file mode 100644
index 000000000..fc0fb6d74
--- /dev/null
+++ b/shacl/src/test/resources/shaclMaxCountBenchmark.ttl
@@ -0,0 +1,17 @@
+@base .
+@prefix ex: .
+@prefix owl: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix sh: .
+@prefix xsd: .
+
+ex:PersonShape
+ a sh:NodeShape ;
+ sh:targetClass rdfs:Resource ;
+ sh:property ex:PersonShapeProperty .
+
+
+ex:PersonShapeProperty
+ sh:path rdfs:label ;
+ sh:maxCount 1 .
\ No newline at end of file
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case1/query1.rq
new file mode 100644
index 000000000..1e1db0745
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case1/query1.rq
@@ -0,0 +1,13 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows ex:peter.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case2/query1.rq
new file mode 100644
index 000000000..2433dceb5
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case2/query1.rq
@@ -0,0 +1,12 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 ex:knows ex:peter.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case2/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case2/query2.rq
new file mode 100644
index 000000000..93fb72304
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case2/query2.rq
@@ -0,0 +1,12 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person .
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case3/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case3/query1.rq
new file mode 100644
index 000000000..4fe46ddbe
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case3/query1.rq
@@ -0,0 +1,15 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows ex:peter.
+
+ex:peter a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case3/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case3/query2.rq
new file mode 100644
index 000000000..d6260a23c
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case3/query2.rq
@@ -0,0 +1,12 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+DELETE DATA {
+
+ex:peter a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case4/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case4/query1.rq
new file mode 100644
index 000000000..4fe46ddbe
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case4/query1.rq
@@ -0,0 +1,15 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows ex:peter.
+
+ex:peter a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case4/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case4/query2.rq
new file mode 100644
index 000000000..91340e628
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case4/query2.rq
@@ -0,0 +1,15 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 ex:knows ex:apple.
+
+ex:apple a ex:Company.
+
+}
+
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case5/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case5/query1.rq
new file mode 100644
index 000000000..326bbd793
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case5/query1.rq
@@ -0,0 +1,16 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows ex:peter.
+
+ex:peter a ex:Person.
+ex:steve a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case5/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case5/query2.rq
new file mode 100644
index 000000000..f41dc5eb4
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case5/query2.rq
@@ -0,0 +1,19 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+delete {
+ex:steve a ex:Person.
+
+}
+
+INSERT {
+
+ex:validPerson1 ex:knows ex:steve.
+
+
+}
+ where {?a ?b ?c}
\ No newline at end of file
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case6/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case6/query1.rq
new file mode 100644
index 000000000..3cd382042
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case6/query1.rq
@@ -0,0 +1,15 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows _:b1.
+
+_:b1 a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case6/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case6/query2.rq
new file mode 100644
index 000000000..b541c22f1
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case6/query2.rq
@@ -0,0 +1,13 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+delete {
+ ?b ?c ?d.
+} where {
+ ?a ex:knows ?b.
+ ?b ?c ?d.
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/invalid/case7/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case7/query1.rq
new file mode 100644
index 000000000..90321287d
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/invalid/case7/query1.rq
@@ -0,0 +1,13 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows "peter".
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/shacl.ttl b/shacl/src/test/resources/test-cases/class/targetNode/shacl.ttl
new file mode 100644
index 000000000..53df706ba
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/shacl.ttl
@@ -0,0 +1,16 @@
+@base .
+@prefix ex: .
+@prefix owl: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix sh: .
+@prefix xsd: .
+
+ex:PersonShape
+ a sh:NodeShape ;
+ sh:targetNode ex:validPerson1 ;
+ sh:property [
+ sh:path ex:knows ;
+ sh:class ex:Person ;
+ ] .
+
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/valid/case1/query1.rq
new file mode 100644
index 000000000..4fe46ddbe
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/valid/case1/query1.rq
@@ -0,0 +1,15 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows ex:peter.
+
+ex:peter a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/valid/case2/query1.rq
new file mode 100644
index 000000000..b7d5f6fee
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/valid/case2/query1.rq
@@ -0,0 +1,12 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:peter a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/valid/case2/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/valid/case2/query2.rq
new file mode 100644
index 000000000..1e1db0745
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/valid/case2/query2.rq
@@ -0,0 +1,13 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows ex:peter.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/valid/case3/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/valid/case3/query1.rq
new file mode 100644
index 000000000..891ac22cd
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/valid/case3/query1.rq
@@ -0,0 +1,14 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 ex:knows ex:peter.
+
+ex:peter a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/valid/case3/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/valid/case3/query2.rq
new file mode 100644
index 000000000..93fb72304
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/valid/case3/query2.rq
@@ -0,0 +1,12 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person .
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/class/targetNode/valid/case4/query1.rq
new file mode 100644
index 000000000..4fe46ddbe
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/valid/case4/query1.rq
@@ -0,0 +1,15 @@
+PREFIX ex:
+PREFIX owl:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX sh:
+PREFIX xsd:
+
+INSERT DATA {
+
+ex:validPerson1 a ex:Person ;
+ ex:knows ex:peter.
+
+ex:peter a ex:Person.
+
+}
diff --git a/shacl/src/test/resources/test-cases/class/targetNode/valid/case4/query2.rq b/shacl/src/test/resources/test-cases/class/targetNode/valid/case4/query2.rq
new file mode 100644
index 000000000..2f9b7356d
--- /dev/null
+++ b/shacl/src/test/resources/test-cases/class/targetNode/valid/case4/query2.rq
@@ -0,0 +1,15 @@
+PREFIX ex:
+PREFIX owl: