Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPARQL FILTER() works as inverse to other validators #289

Open
hentoilusose opened this issue Mar 24, 2025 · 2 comments
Open

SPARQL FILTER() works as inverse to other validators #289

hentoilusose opened this issue Mar 24, 2025 · 2 comments

Comments

@hentoilusose
Copy link

Greetings. I'm comparing pySHACL to other validators such as the European Commissions ISAITB. There seems to be divergent behaviour between them in how to interpret FILTER(). An MWE below:

@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix meta: <https://iri.foo.bar/schema/meta/> .
@prefix domain: <https://iri.foo.bar/ontology/domain/> .

meta:SPARQLRule a sh:SPARQLConstraint;
	sh:prefixes [
		sh:declare [
			sh:prefix "domain";
			sh:namespace "https://iri.foo.bar/ontology/domain/"^^xsd:anyURI ;
		]
	];
	sh:select """
		SELECT $this ?declaredLocalIdentifier ?foundLocalIdentifier
		WHERE {
			$this domain:hasLocalIdentifier ?declaredLocalIdentifier .
			BIND(REPLACE(STR($this), '^(.+/|.+#)', '', '') AS ?foundLocalIdentifier)
			FILTER(?declaredLocalIdentifier != ?foundLocalIdentifier)
		}""" ;
	sh:severity sh:Violation;
	sh:message "Found identifier was: {?foundLocalIdentifier}, declared identifier was: {?declaredLocalIdentifier}.".

meta:SPARQLShape a sh:NodeShape;
	domain:hasLocalIdentifier "SPARQLShape"^^xsd:NCName;
	sh:targetClass sh:NodeShape;
	sh:sparql meta:SPARQLRule;
	sh:severity sh:Violation.

When validating this shapes graph with itself, ISAITB sees no violation as all local identifiers stripped from the URI are identical to the declared ones, whereas pySHACL does. If I flip the equality assertion to =, pySHACL sees no Violation while ISAITB does.

To my understanding each individual result should be included in the result set if FILTER() evaluation is true - which it in this case it isn't (as the literal NCName and the identifier extracted from URI are identical). In the least there is discrepancy between validators but my current understanding is that pySHACL should evaluate FILTER() in inverse. Am I mistaken?

Here are the validation message first from pySHACL 0.30.0:

[] a sh:ValidationReport ;
    sh:conforms false ;
    sh:result [ a sh:ValidationResult ;
            sh:focusNode meta:SPARQLShape ;
            sh:resultMessage "Found identifier was: SPARQLShape, declared identifier was: SPARQLShape." ;
            sh:resultSeverity sh:Violation ;
            sh:sourceConstraint meta:SPARQLRule ;
            sh:sourceConstraintComponent sh:SPARQLConstraintComponent ;
            sh:sourceShape meta:SPARQLShape ;
            sh:value meta:SPARQLShape ] .

And from ISAITB validator 1.7.0:

[ rdf:type     sh:ValidationReport;
  sh:conforms  true
] .
@ashleysommer
Copy link
Collaborator

Hi @hentoilusose
This sounds like it might be an RDFLib issue, not a PySHACL issue.

PySHACL uses the SPARQL execution engine from the RDFLib python library, and the FILTER() function is part of that.

Are you in a position to be able to try to re-create the bug using a normal SPARQL query in RDFLib against an RDFLib graph?

@hentoilusose
Copy link
Author

Thanks, continued here: RDFLib/rdflib#3096

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants