I am currently developing a piece of software that uses rules from property shapes (namely SHACL constraints) to generate forms which have their information inserted into triplestores over a SPARQL endpoint. The main use cases are for users entering data about a new entity, and users filling in missing data for existing entities in a knowledge graph. Until recently I have been running version 7.2 of virtuoso on my system. I have recently tested some of the queries (an example of such a query is below) on version 8.3 of Virtuoso and discovered that many queries that were working prior are now returning the error
‘Virtuoso 37000 Error SP031: SPARQL compiler: Internal error: sparp_rewrite_qm_optloop(): Infinite optimization loop?’.
It appears that these errors are occurring when running a sub query on a named graph which differs from the named graph of the ambient query. I should also note I have also noticed found that the behaviour of zero or one paths as part of an alternate path (e.g. rdf:rest*/rdf:first) have caused what appears to be unexpected errors both in version 7.2 and 8.3 of virtuoso but I do not believe this to be the cause as I never saw infinite optimization loops in virtuoso 7.2.
The below query is designed to extract all first order properties that we know apply to a target in a knowledge graph. It first queries the knowledge graph to get all predicates attached to the target and all classes that the target belongs to (including implicit classes). It then uses sh:targetNode, sh:targetSubjectsOf, sh:targetObjectsOf and sh:targetClass labels in the shacl/shapes graph to establish the applicable shacls and then returning a filtered dictionary of property shapes.
I have highlighted the portion of the query that appears to be causing the error (I have run some tests using only this section of code).
PREFIX sh: <http://www.w3.org/ns/shacl#>
SELECT DISTINCT (concat("{",group_concat(distinct ?tproperties; separator="},{"),"}") AS ?r) {
{SELECT DISTINCT ?t (concat("'",group_concat(distinct ?properties; separator="},{'")) AS ?x)
{SELECT DISTINCT ?t (group_concat(distinct ?prop; separator=",'") AS ?properties)
FROM <http://shacl>
WHERE {
{?s sh:targetNode ?t}
UNION {?s sh:targetSubjectsOf ?p}
UNION {?s sh:targetObjectsOf ?pi}
UNION {?s sh:targetClass ?class}
{SELECT DISTINCT ?s ?n ?pa (group_concat(distinct ?obs; separator="','") AS ?ob)
WHERE {?s sh:property ?n . ?n ?pa ?oa OPTIONAL {?oa (rdf:rest*/rdf:first)? ?obs}
FILTER (!isBlank(?obs) && ?obs != rdf:nil)}}
{SELECT DISTINCT ?t ?class ?p ?pi
FROM <some_knowledge_graph>
WHERE {
{SELECT DISTINCT ?t ?class ?p WHERE {?t ?p ?os OPTIONAL {?p rdfs:subPropertyOf*/rdfs:domain+/rdfs:subClassOf* ?class}}}
UNION {SELECT DISTINCT ?t ?class ?pi WHERE {?s ?pi ?t OPTIONAL {?pi rdfs:subPropertyOf*/rdfs:range+/rdfs:subClassOf* ?class}}}
UNION {SELECT DISTINCT ?t ?class WHERE {?t a/rdfs:subClassOf* ?class}}
FILTER (?p != rdf:type && ?p != rdfs:subPropertyOf && ?pi != rdf:type && ?pi != rdfs:subPropertyOf)}}
VALUES (?t) {(<some_target>)}
FILTER (NOT EXISTS { SELECT ?n { ?n ?q ?w . VALUES (?w) {(sh:Info)}}} && EXISTS {SELECT ?o { ?o sh:severity ?x}})
BIND(REPLACE(STR(?pa), sh:, "") AS ?pa2)
BIND(IF(?pa = sh:severity, REPLACE(STR(?ob), sh:, ""),?ob) AS ?ob2)
BIND(CONCAT(IF(?pa2 = 'path' || ?pa2='inversePath', CONCAT("pathType':'", ?pa2, "','path"), ?pa2), IF(regex(?ob, ",", "i") && !regex(?pa2, "message", "i"),"':['","':'"), ?ob2, IF(regex(?ob, ",", "i") ,"']","'")) AS ?prop)}
GROUP BY ?t ?n}
GROUP BY ?t}
BIND (CONCAT("'", ?t, "':{", ?x, "}") AS ?tproperties)}