blazegraph / database

Blazegraph High Performance Graph Database
GNU General Public License v2.0
872 stars 170 forks source link

Throwing exception on complicated query that works in other triplestores #231

Open cuddihyge opened 2 years ago

cuddihyge commented 2 years ago

This big ol' query (works in Fuseki) fails in every mode of namespace I could create. Below is the error message for the default namespace/kb

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select distinct ?Property ?Domain ?Range
    FROM <http://rack001/model>
    WHERE {
  {
        #### Outer UNION: domain and range

    # ?Property optionally has a rdfs:domain
    {
      # No domain
         # Note that ?Property needs to be repeated in each union to make the FILTER NOT EXISTS work
         # Since FILTERS only apply to inner most block
      {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } .
      FILTER NOT EXISTS { ?Property rdfs:domain ?Domain }
    } UNION {
         # domain is a simple non-blank node
      # rdf:Property added so we match SadlListModel:List
      {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } union { ?Property a rdf:Property } .
      ?Property rdfs:domain ?Domain filter (!regex(str(?Domain),\'^(nodeID://|_:)\') || regex(str(?Domain),\'XML\')) .
    } UNION {
         # domain is a union
      {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } .
      ?Property rdfs:domain ?d0 .
      ?d0 owl:unionOf ?y1.{ ?y1 rdf:rest* ?Rest13. ?Rest13 rdf:first ?Domain filter (!regex(str(?Domain),\'^(nodeID://|_:)\') || regex(str(?Domain),\'XML\')) . }
    }

    # ?Property optional has rdfs:range
    {
      # No range
      # Once again ?Property is repeated in each union to make the FILTER NOT EXISTS work
      # rdf:Property added so we match SadlListModel:List
      {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } union { ?Property a rdf:Property } .
      FILTER NOT EXISTS { ?Property rdfs:range ?Range }
    } UNION {
      # range is a simple non-blank node
      {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } .
      ?Property rdfs:range ?Range filter (!regex(str(?Range),\'^(nodeID://|_:)\') || regex(str(?Range),\'XML\')) .
    } UNION {
      # range is a union
      {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } .
      ?Property rdfs:range ?r0 .
      ?r0 owl:unionOf ?r1.{ ?r1 rdf:rest* ?Rest14. ?Rest14 rdf:first ?Range filter (!regex(str(?Range),\'^(nodeID://|_:)\') || regex(str(?Range),\'XML\')) . }
    } UNION {
      # range is a blanknode subclass.
      # Added to partially support SadlListModel:List by skipping parameterized lists up their parents: Unparameterized list.
      {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } .
      ?Property rdfs:range ?r0 filter (regex(str(?r0),\'^(nodeID://|_:)\')) .
      ?r0 rdfs:subClassOf ?Range.filter (!regex(str(?Range),\'^(nodeID://|_:)\') || regex(str(?Range),\'XML\'))
    }

  } UNION {
    #### Outer UNION: restriction ####

    # get the restriction
    {?Property a owl:ObjectProperty. } union { ?Property a owl:DatatypeProperty } .
    ?rest owl:onProperty ?Property.
    ?rest rdf:type owl:Restriction.

    # range
   {
      # restriction has simple range or allValuesFrom or someValuesFrom a non-blank node
      ?rest (owl:onClass|owl:allValuesFrom|owl:someValuesFrom) ?Range filter (!regex(str(?Range),\'^(nodeID://|_:)\') || regex(str(?Range),\'XML\')) .
    } UNION {
      # restriction has range is a union
      ?rest (owl:onClass|owl:allValuesFrom|owl:someValuesFrom) ?y.
      ?y owl:unionOf ?z. { ?z rdf:rest* ?Rest15. ?Rest15 rdf:first ?Range filter (!regex(str(?Range),\'^(nodeID://|_:)\') || regex(str(?Range),\'XML\')) . }
    }

    {
      # restriction is simple subClassOf non-blank node
      ?Domain rdfs:subClassOf ?rest filter (!regex(str(?Domain),\'^(nodeID://|_:)\') || regex(str(?Domain),\'XML\')) .
    } UNION {
      # restriction is subClassOf union
      ?dx1 rdfs:subClassOf ?rest .
      ?dx1 owl:unionOf ?dx2. { ?dx2 rdf:rest* ?Rest16. ?Rest16 rdf:first ?Domain filter (!regex(str(?Domain),\'^(nodeID://|_:)\') || regex(str(?Domain),\'XML\')) . }
    }
  }
}

error is

java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.ClassCastException: class com.bigdata.rdf.sparql.ast.UnionNode cannot be cast to class com.bigdata.rdf.sparql.ast.JoinGroupNode (com.bigdata.rdf.sparql.ast.UnionNode and com.bigdata.rdf.sparql.ast.JoinGroupNode are in unnamed module of loader \'app\')
  at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
  at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
  at com.bigdata.rdf.sail.webapp.BigdataServlet.submitApiTask(BigdataServlet.java:294)
  at com.bigdata.rdf.sail.webapp.QueryServlet.doSparqlQuery(QueryServlet.java:678)
  at com.bigdata.rdf.sail.webapp.QueryServlet.doPost(QueryServlet.java:275)
  at com.bigdata.rdf.sail.webapp.RESTServlet.doPost(RESTServlet.java:269)
  at com.bigdata.rdf.sail.webapp.MultiTenancyServlet.doPost(MultiTenancyServlet.java:195)
...
cuddihyge commented 2 years ago

This equivalent query works. It replaces some inner UNIONS and some (prop1|prop2|prop3) clauses with VALUES clauses. So the issue with Blazegraph is in NESTING of UNIONS, where the ?s (prop1|prop2|prop3) ?o type of statement also counts as a union.

(Apologies for the backslashed single quotes in the original comment above, they are removed here too. That was not related.)


PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select distinct ?Property ?Domain ?Range
    FROM <http://rack001/model>
    WHERE {
  {
        #### Outer UNION: domain and range

    # ?Property optionally has a rdfs:domain
    {
      # No domain
         # Note that ?Property needs to be repeated in each union to make the FILTER NOT EXISTS work
         # Since FILTERS only apply to inner most block
      VALUES ?t {owl:ObjectProperty owl:DatatypeProperty } .
      ?Property a ?t.
      FILTER NOT EXISTS { ?Property rdfs:domain ?Domain }
    } UNION {
         # domain is a simple non-blank node
      # rdf:Property added so we match SadlListModel:List
      VALUES ?t {owl:ObjectProperty owl:DatatypeProperty rdf:Property} .
      ?Property a ?t.
      ?Property rdfs:domain ?Domain filter (!regex(str(?Domain),'^(nodeID://|_:)') || regex(str(?Domain),'XML')) .
    } UNION {
         # domain is a union
      VALUES ?t {owl:ObjectProperty owl:DatatypeProperty } .
      ?Property a ?t.
      ?Property rdfs:domain ?d0 .
      ?d0 owl:unionOf ?y1.{ ?y1 rdf:rest* ?Rest13. ?Rest13 rdf:first ?Domain filter (!regex(str(?Domain),'^(nodeID://|_:)') || regex(str(?Domain),'XML')) . }
    }

    # ?Property optional has rdfs:range
    {
      # No range
      # Once again ?Property is repeated in each union to make the FILTER NOT EXISTS work
      # rdf:Property added so we match SadlListModel:List
      VALUES ?t {owl:ObjectProperty owl:DatatypeProperty rdf:Property} .
      ?Property a ?t.
      FILTER NOT EXISTS { ?Property rdfs:range ?Range }
    } UNION {
      # range is a simple non-blank node
      VALUES ?t {owl:ObjectProperty owl:DatatypeProperty} .
      ?Property a ?t.
      ?Property rdfs:range ?Range filter (!regex(str(?Range),'^(nodeID://|_:)') || regex(str(?Range),'XML')) .
    } UNION {
      # range is a union
      VALUES ?t {owl:ObjectProperty owl:DatatypeProperty} .
      ?Property a ?t.
      ?Property rdfs:range ?r0 .
      ?r0 owl:unionOf ?r1.{ ?r1 rdf:rest* ?Rest14. ?Rest14 rdf:first ?Range filter (!regex(str(?Range),'^(nodeID://|_:)') || regex(str(?Range),'XML')) . }
    } UNION {
      # range is a blanknode subclass.
      # Added to partially support SadlListModel:List by skipping parameterized lists up their parents: Unparameterized list.
      VALUES ?t {owl:ObjectProperty owl:DatatypeProperty} .
      ?Property a ?t.
      ?Property rdfs:range ?r0 filter (regex(str(?r0),'^(nodeID://|_:)')) .
      ?r0 rdfs:subClassOf ?Range.filter (!regex(str(?Range),'^(nodeID://|_:)') || regex(str(?Range),'XML'))
    }

  } UNION {
    #### Outer UNION: restriction ####

    # get the restriction
    VALUES ?t {owl:ObjectPropertyowl:DatatypeProperty } .
    ?Property a ?t.
    ?rest owl:onProperty ?Property.
    ?rest rdf:type owl:Restriction.

    # range
    VALUES ?p { owl:onClass owl:allValuesFrom owl:someValuesFrom } .
    {
      # restriction has simple range or allValuesFrom or someValuesFrom a non-blank node
      ?rest ?p ?Range filter (!regex(str(?Range),'^(nodeID://|_:)') || regex(str(?Range),'XML')) .
    } UNION {
      # restriction has range is a union
      ?rest ?p ?y.
      ?y owl:unionOf ?z. { ?z rdf:rest* ?Rest15. ?Rest15 rdf:first ?Range filter (!regex(str(?Range),'^(nodeID://|_:)') || regex(str(?Range),'XML')) . }
    }

    {
      # restriction is simple subClassOf non-blank node
      ?Domain rdfs:subClassOf ?rest filter (!regex(str(?Domain),'^(nodeID://|_:)') || regex(str(?Domain),'XML')) .
    } UNION {
      # restriction is subClassOf union
      ?dx1 rdfs:subClassOf ?rest .
      ?dx1 owl:unionOf ?dx2. { ?dx2 rdf:rest* ?Rest16. ?Rest16 rdf:first ?Domain filter (!regex(str(?Domain),'^(nodeID://|_:)') || regex(str(?Domain),'XML')) . }
    }
  }
}