RDFLib / pySHACL

A Python validator for SHACL
Apache License 2.0
241 stars 63 forks source link

SPARQL constraints depend on variable names #196

Closed jcbiddle closed 10 months ago

jcbiddle commented 10 months ago

I'm attempting to write a SHACL-SPARQL constraint that will produce a violation if the target is the object of more than one instance of the same predicate, e.g.

sh:sparql
    [
        sh:select """
        PREFIX ex: <http://example.com#>
        SELECT ?thing1 ?thing2
        WHERE {
        ?thing1 ex:relatedTo $this .
        ?thing2 ex:relatedTo $this .
        FILTER(STR(?thing1) < STR(?thing2))
        }
        """ ;
    ] ;

From my reading of the SHACL, this should produce a violation for data such as

PREFIX ex: <http://example.com#>
ex:Parent1 ex:relatedTo ex:Child .
ex:Parent2 ex:relatedTo ex:Child .

if ex:Child is a focus node. However, the current implementation only keeps validation results if this, value or path are variables in the query. As far as I can tell, this restriction seems to go against the expected behaviour as outlined in the SHACL specification.

ashleysommer commented 10 months ago

Hi @jcbiddle, thanks for submitting your issue.

My understanding of the reading of the spec at section 5.2

SPARQL-based constraints have exactly one value for the property sh:select. The value of sh:select is a literal of datatype xsd:string. The class sh:SPARQLConstraint is defined in the SHACL vocabulary and may be used as the type of these constraints (although no type is required). Using the prefix handling rules, the value of sh:select is a valid SPARQL 1.1 SELECT query. The SPARQL query derived from the value of sh:select projects the variable this in the SELECT clause.

It states "the query projects the variable this in the SELECT clause". My interpretation of that is the SELECT clause must contain the variable ?this. All of the examples shown in the SHACL spec document for SHACL-SPAQRL constraints do contain ?this in the SELECT clause, and all of the SHACL-SPARQL test cases in the W3C-SHT and DASH SHACL test suites also contain ?this in the SELECT clause. By passing those test cases, it demonstrates PySHACL is operating in the correct manner.

Simply adding ?this to your select clause will fix the issue you are seeing:

sh:sparql
    [
        sh:select """
        PREFIX ex: <http://example.com#>
        SELECT ?this ?thing1 ?thing2
        WHERE {
        ?thing1 ex:relatedTo $this .
        ?thing2 ex:relatedTo $this .
        FILTER(STR(?thing1) < STR(?thing2))
        }
        """ ;
    ] ;
jcbiddle commented 10 months ago

Thanks for your response @ashleysommer, I missed the implication of that last sentence. I'll close this issue.