Skip to content

Commit

Permalink
GH-5112 various bugs related to the ShaclSail (#5117)
Browse files Browse the repository at this point in the history
  • Loading branch information
hmottestad authored Aug 27, 2024
2 parents eab7272 + 235d3af commit 5c956e1
Show file tree
Hide file tree
Showing 96 changed files with 2,189 additions and 138 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private QueryValueEvaluationStepSupplier() {
}

public static QueryValueEvaluationStep prepareStr(QueryValueEvaluationStep arg, ValueFactory valueFactory) {
return make(arg, "Unkown constant argument for STR()", bs -> str(arg, valueFactory, bs));
return make(arg, "Unknown constant argument for STR()", bs -> str(arg, valueFactory, bs));
}

private static Value str(QueryValueEvaluationStep arg, ValueFactory valueFactory, BindingSet bindings) {
Expand All @@ -67,7 +67,7 @@ private static Value str(QueryValueEvaluationStep arg, ValueFactory valueFactory
return valueFactory.createLiteral(literal.getLabel());
}
} else {
throw new ValueExprEvaluationException("Unkown constant argument for STR()");
throw new ValueExprEvaluationException("Unknown constant argument for STR()");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class PeekMarkIterator<E> implements CloseableIteration<E> {

private boolean closed;

PeekMarkIterator(CloseableIteration<E> iterator) {
public PeekMarkIterator(CloseableIteration<E> iterator) {
this.iterator = iterator;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ private void processError() throws IOException, QueryResultParseException {
} else if (errTypeFlag == QUERY_EVALUATION_ERROR) {
errType = QueryErrorType.QUERY_EVALUATION_ERROR;
} else {
throw new QueryResultParseException("Unkown error type: " + errTypeFlag);
throw new QueryResultParseException("Unknown error type: " + errTypeFlag);
}

String msg = readString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ abstract class ShaclSailBaseConfiguration extends NotifyingSailWrapper {
private static final Logger logger = LoggerFactory.getLogger(ShaclSailBaseConfiguration.class);

// Field used to control if the new SPARQL based validation should be enabled or disabled. Enabled by default.
final boolean sparqlValidation;
boolean sparqlValidation;

private boolean parallelValidation = ShaclSailConfig.PARALLEL_VALIDATION_DEFAULT;
private boolean logValidationPlans = ShaclSailConfig.LOG_VALIDATION_PLANS_DEFAULT;
Expand Down Expand Up @@ -375,4 +375,5 @@ public Set<IRI> getShapesGraphs() {
public void setShapesGraphs(Set<IRI> shapesGraphs) {
this.shapesGraphs = shapesGraphs;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,13 @@ public ValidationResultIterator performValidation() {
validationResults = new ValidationResultIterator(iterator, effectiveValidationResultsLimitPerConstraint);
return validationResults;
} catch (Throwable e) {
logger.warn("Error validating SHACL Shape {}", shape.getId(), e);
logger.warn("Error validating SHACL Shape\n{}", shape, e);
logger.warn("Internal error while trying to validate SHACL Shape {}", shape.getId(), e);
logger.warn("Internal error while trying to validate SHACL Shape\n{}", shape, e);
if (e instanceof Error) {
throw e;
}
throw new SailException("Error validating SHACL Shape " + shape.getId() + "\n" + shape, e);
throw new SailException(
"Internal error while trying to validate SHACL Shape " + shape.getId() + "\n" + shape, e);
} finally {
handlePostLogging(before, validationResults);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,53 @@
import org.eclipse.rdf4j.model.vocabulary.SHACL;

public enum SourceConstraintComponent {
MaxCountConstraintComponent(SHACL.MAX_COUNT_CONSTRAINT_COMPONENT, false),
MinCountConstraintComponent(SHACL.MIN_COUNT_CONSTRAINT_COMPONENT, false),

DatatypeConstraintComponent(SHACL.DATATYPE_CONSTRAINT_COMPONENT, true),
NodeKindConstraintComponent(SHACL.NODE_KIND_CONSTRAINT_COMPONENT, true),
ClassConstraintComponent(SHACL.CLASS_CONSTRAINT_COMPONENT, true),

PatternConstraintComponent(SHACL.PATTERN_CONSTRAINT_COMPONENT, true),
UniqueLangConstraintComponent(SHACL.UNIQUE_LANG_CONSTRAINT_COMPONENT, false),
LanguageInConstraintComponent(SHACL.LANGUAGE_IN_CONSTRAINT_COMPONENT, true),
MaxLengthConstraintComponent(SHACL.MAX_LENGTH_CONSTRAINT_COMPONENT, true),
MinLengthConstraintComponent(SHACL.MIN_LENGTH_CONSTRAINT_COMPONENT, true),

InConstraintComponent(SHACL.IN_CONSTRAINT_COMPONENT, true),
HasValueConstraintComponent(SHACL.HAS_VALUE_CONSTRAINT_COMPONENT, false),
HasValueInConstraintComponent(DASH.HasValueInConstraintComponent, false),
ClosedConstraintComponent(SHACL.CLOSED_CONSTRAINT_COMPONENT, true),

MinExclusiveConstraintComponent(SHACL.MIN_EXCLUSIVE_CONSTRAINT_COMPONENT, true),
MaxExclusiveConstraintComponent(SHACL.MAX_EXCLUSIVE_CONSTRAINT_COMPONENT, true),
MaxInclusiveConstraintComponent(SHACL.MAX_INCLUSIVE_CONSTRAINT_COMPONENT, true),
MinInclusiveConstraintComponent(SHACL.MIN_INCLUSIVE_CONSTRAINT_COMPONENT, true),

AndConstraintComponent(SHACL.AND_CONSTRAINT_COMPONENT, true),
OrConstraintComponent(SHACL.OR_CONSTRAINT_COMPONENT, true),
NotConstraintComponent(SHACL.NOT_CONSTRAINT_COMPONENT, true),
XoneConstraintComponent(SHACL.XONE_CONSTRAINT_COMPONENT, true),

DisjointConstraintComponent(SHACL.DISJOINT_CONSTRAINT_COMPONENT, true),
EqualsConstraintComponent(SHACL.EQUALS_CONSTRAINT_COMPONENT, true),
LessThanConstraintComponent(SHACL.LESS_THAN_CONSTRAINT_COMPONENT, true),
MaxCountConstraintComponent(SHACL.MAX_COUNT_CONSTRAINT_COMPONENT, ProducesValidationResultValue.NEVER),
MinCountConstraintComponent(SHACL.MIN_COUNT_CONSTRAINT_COMPONENT, ProducesValidationResultValue.NEVER),

DatatypeConstraintComponent(SHACL.DATATYPE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
NodeKindConstraintComponent(SHACL.NODE_KIND_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
ClassConstraintComponent(SHACL.CLASS_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),

PatternConstraintComponent(SHACL.PATTERN_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
UniqueLangConstraintComponent(SHACL.UNIQUE_LANG_CONSTRAINT_COMPONENT, ProducesValidationResultValue.NEVER),
LanguageInConstraintComponent(SHACL.LANGUAGE_IN_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
MaxLengthConstraintComponent(SHACL.MAX_LENGTH_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
MinLengthConstraintComponent(SHACL.MIN_LENGTH_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),

InConstraintComponent(SHACL.IN_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
HasValueConstraintComponent(SHACL.HAS_VALUE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.NEVER),
HasValueInConstraintComponent(DASH.HasValueInConstraintComponent, ProducesValidationResultValue.NEVER),
ClosedConstraintComponent(SHACL.CLOSED_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),

MinExclusiveConstraintComponent(SHACL.MIN_EXCLUSIVE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
MaxExclusiveConstraintComponent(SHACL.MAX_EXCLUSIVE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
MaxInclusiveConstraintComponent(SHACL.MAX_INCLUSIVE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
MinInclusiveConstraintComponent(SHACL.MIN_INCLUSIVE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),

AndConstraintComponent(SHACL.AND_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
OrConstraintComponent(SHACL.OR_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
NotConstraintComponent(SHACL.NOT_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
XoneConstraintComponent(SHACL.XONE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),

DisjointConstraintComponent(SHACL.DISJOINT_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
EqualsConstraintComponent(SHACL.EQUALS_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
LessThanConstraintComponent(SHACL.LESS_THAN_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
LessThanOrEqualsConstraintComponent(SHACL.LESS_THAN_OR_EQUALS_CONSTRAINT_COMPONENT,
true),
ProducesValidationResultValue.ALWAYS),

QualifiedMaxCountConstraintComponent(SHACL.QUALIFIED_MAX_COUNT_CONSTRAINT_COMPONENT,
false),
ProducesValidationResultValue.NEVER),
QualifiedMinCountConstraintComponent(SHACL.QUALIFIED_MIN_COUNT_CONSTRAINT_COMPONENT,
false),
NodeConstraintComponent(SHACL.NODE_CONSTRAINT_COMPONENT, true),
PropertyConstraintComponent(SHACL.PROPERTY_CONSTRAINT_COMPONENT, false),
ProducesValidationResultValue.NEVER),
NodeConstraintComponent(SHACL.NODE_CONSTRAINT_COMPONENT, ProducesValidationResultValue.ALWAYS),
PropertyConstraintComponent(SHACL.PROPERTY_CONSTRAINT_COMPONENT, ProducesValidationResultValue.NEVER),

SPARQLConstraintComponent(SHACL.SPARQL_CONSTRAINT_COMPONENT, true);
SPARQLConstraintComponent(SHACL.SPARQL_CONSTRAINT_COMPONENT, ProducesValidationResultValue.SOMETIMES);

private final IRI iri;
private final boolean producesValidationResultValue;
private final ProducesValidationResultValue producesValidationResultValue;

SourceConstraintComponent(IRI iri, boolean producesValidationResultValue) {
SourceConstraintComponent(IRI iri, ProducesValidationResultValue producesValidationResultValue) {
this.iri = iri;
this.producesValidationResultValue = producesValidationResultValue;
}
Expand All @@ -72,6 +72,16 @@ public IRI getIri() {
}

public boolean producesValidationResultValue() {
return producesValidationResultValue;
return producesValidationResultValue != ProducesValidationResultValue.NEVER;
}

public boolean alwaysProducesValidationResultValue() {
return producesValidationResultValue == ProducesValidationResultValue.ALWAYS;
}

private enum ProducesValidationResultValue {
ALWAYS,
NEVER,
SOMETIMES
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public ValidationQuery(Collection<Namespace> namespaces, String query, List<Vari
propertyShapeWithValue = false;
valueIndex = variables.size();
assert constraintComponent == null
|| !constraintComponent.getConstraintComponent().producesValidationResultValue();
|| !constraintComponent.getConstraintComponent().alwaysProducesValidationResultValue();
}
} else {
targetIndex = variables.size() - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,18 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class SimpleAbstractConstraintComponent extends AbstractConstraintComponent {
public abstract class AbstractSimpleConstraintComponent extends AbstractConstraintComponent {

private static final Logger logger = LoggerFactory.getLogger(SimpleAbstractConstraintComponent.class);
private static final Logger logger = LoggerFactory.getLogger(AbstractSimpleConstraintComponent.class);

private Resource id;
TargetChain targetChain;

public SimpleAbstractConstraintComponent(Resource id) {
public AbstractSimpleConstraintComponent(Resource id) {
this.id = id;
}

public SimpleAbstractConstraintComponent() {
public AbstractSimpleConstraintComponent() {

}

Expand Down Expand Up @@ -159,15 +159,24 @@ private PlanNode getPlanNodeForOverrideTargetNode(ConnectionsGroup connectionsGr
validationSettings.getDataGraph(), scope);
allTargets = getFilterAttacherWithNegation(negatePlan, allTargets);

return Unique.getInstance(allTargets, true);
if (effectiveTarget.size() > 1) {
allTargets = Unique.getInstance(allTargets, true);
}
return allTargets;
} else {
return effectiveTarget.extend(overrideTargetPlanNode, connectionsGroup,
PlanNode extend = effectiveTarget.extend(overrideTargetPlanNode, connectionsGroup,
validationSettings.getDataGraph(), scope,
EffectiveTarget.Extend.right,
false,
p -> getFilterAttacherWithNegation(negatePlan, p)
);

if (effectiveTarget.size() > 1) {
extend = Unique.getInstance(extend, true);
}

return extend;

}

} else {
Expand All @@ -184,14 +193,22 @@ private PlanNode getPlanNodeForOverrideTargetNode(ConnectionsGroup connectionsGr

allTargets = getFilterAttacherWithNegation(negatePlan, allTargets);

return Unique.getInstance(allTargets, true);
if (effectiveTarget.size() > 1) {
allTargets = Unique.getInstance(allTargets, true);
}

return allTargets;

} else {

overrideTargetPlanNode = effectiveTarget.extend(overrideTargetPlanNode, connectionsGroup,
validationSettings.getDataGraph(), scope,
EffectiveTarget.Extend.right, false, null);

if (effectiveTarget.size() > 1) {
overrideTargetPlanNode = Unique.getInstance(overrideTargetPlanNode, true);
}

planNode = new BulkedExternalInnerJoin(overrideTargetPlanNode,
connectionsGroup.getBaseConnection(),
validationSettings.getDataGraph(), path.get()
Expand Down Expand Up @@ -314,13 +331,25 @@ String literalToString(Literal literal) {
@Override
public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope,
StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) {

if (scope == Scope.propertyShape) {
PlanNode allTargetsPlan = getTargetChain()
.getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(),
stableRandomVariableProvider)
.getPlanNode(connectionsGroup, dataGraph, Scope.nodeShape, true, null);

return Unique.getInstance(new ShiftToPropertyShape(allTargetsPlan), true);
EffectiveTarget effectiveTarget = getTargetChain()
.getEffectiveTarget(
Scope.nodeShape,
connectionsGroup.getRdfsSubClassOfReasoner(),
stableRandomVariableProvider
);

PlanNode allTargetsPlan = effectiveTarget
.getPlanNode(
connectionsGroup,
dataGraph, Scope.nodeShape,
true,
null
);

return Unique.getInstance(new ShiftToPropertyShape(allTargetsPlan), effectiveTarget.size() > 1);
}
return EmptyNode.getInstance();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach;
import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery;
import org.eclipse.rdf4j.sail.shacl.ast.paths.Path;
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AllTargetsPlanNode;
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BufferedSplitter;
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalInnerJoin;
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.EmptyNode;
Expand Down Expand Up @@ -85,10 +86,30 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections
PlanNode addedTargets;

if (overrideTargetNode != null) {
addedTargets = effectiveTarget.extend(overrideTargetNode.getPlanNode(), connectionsGroup,
validationSettings.getDataGraph(), scope,
EffectiveTarget.Extend.right,
false, null);
PlanNode planNode = overrideTargetNode.getPlanNode();
if (planNode instanceof AllTargetsPlanNode) {
// We are cheating a bit here by retrieving all the targets and values at the same time by
// pretending to be in node shape scope and then shifting the results back to property shape scope
PlanNode allTargets = getTargetChain()
.getEffectiveTarget(Scope.nodeShape,
connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider)
.getAllTargets(connectionsGroup, validationSettings.getDataGraph(), Scope.nodeShape);
allTargets = new ShiftToPropertyShape(allTargets);

// filter by type against the base sail
allTargets = new FilterByPredicateObject(
connectionsGroup.getBaseConnection(),
validationSettings.getDataGraph(), RDF.TYPE, clazzSet,
allTargets, false, FilterByPredicateObject.FilterOn.value, true);

return allTargets;

} else {
addedTargets = effectiveTarget.extend(planNode, connectionsGroup,
validationSettings.getDataGraph(), scope,
EffectiveTarget.Extend.right,
false, null);
}

} else {
BufferedSplitter addedTargetsBufferedSplitter = new BufferedSplitter(
Expand All @@ -98,7 +119,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections
PlanNode addedByPath = path.getAllAdded(connectionsGroup, validationSettings.getDataGraph(), null);

addedByPath = effectiveTarget.getTargetFilter(connectionsGroup,
validationSettings.getDataGraph(), Unique.getInstance(new TrimToTarget(addedByPath), false));
validationSettings.getDataGraph(), Unique.getInstance(new TrimToTarget(addedByPath), true));

addedByPath = new ReduceTargets(addedByPath, addedTargetsBufferedSplitter.getPlanNode());

Expand Down Expand Up @@ -132,6 +153,12 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections
addedTargets = Unique.getInstance(addedTargets, false);
}

int size = effectiveTarget.size();

if (size > 1) {
addedTargets = Unique.getInstance(addedTargets, true);
}

PlanNode falseNode = new BulkedExternalInnerJoin(
addedTargets,
connectionsGroup.getBaseConnection(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.FilterPlanNode;
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode;

public class DatatypeConstraintComponent extends SimpleAbstractConstraintComponent {
public class DatatypeConstraintComponent extends AbstractSimpleConstraintComponent {

private final CoreDatatype coreDatatype;
private final IRI datatype;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ValueInFilter;
import org.eclipse.rdf4j.sail.shacl.wrapper.shape.ShapeSource;

public class InConstraintComponent extends SimpleAbstractConstraintComponent {
public class InConstraintComponent extends AbstractSimpleConstraintComponent {

private final Set<Value> in;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode;
import org.eclipse.rdf4j.sail.shacl.wrapper.shape.ShapeSource;

public class LanguageInConstraintComponent extends SimpleAbstractConstraintComponent {
public class LanguageInConstraintComponent extends AbstractSimpleConstraintComponent {

private final List<String> languageIn;
private final ArrayList<String> languageRanges;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.LiteralComparatorFilter;
import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode;

public class MaxExclusiveConstraintComponent extends SimpleAbstractConstraintComponent {
public class MaxExclusiveConstraintComponent extends AbstractSimpleConstraintComponent {

Literal maxExclusive;

Expand Down
Loading

0 comments on commit 5c956e1

Please sign in to comment.