Missing results when reasoner on and owl:sameAs present

When I query with the reasoner on, expected results disappear when an owl:sameAs relationship is present. I think this is a bug in the query rewriting.

Environment

  • Stardog version = 7.4.0
  • OS = Mac 10.15.x

Database configuration

  • reasoning.sameas = ON (I also tried FULL)
  • query.all.graphs = TRUE
  • query.pp.contexts = (tried both TRUE and FALSE)

Steps to reproduce

Setup data in an empty database:

prefix ex: <http://example.com/>
prefix owl: <http://www.w3.org/2002/07/owl#>
insert data {
    graph <http://example.com> {ex:1 ex:r1 ex:2}
    graph <http://example.com> {ex:2 owl:sameAs ex:2-alt}
}

Query to reproduce

prefix ex: <http://example.com/>
select *
{
    bind(ex:1 as ?s)
    bind(ex:2 as ?o)
    ?s ?p ?o
    filter(
        exists {?s ex:r1 ?o}
        || false
    )
}

Expected result

http://example.com/1 http://example.com/2
or
http://example.com/1 http://example.com/2-alt

Actual result

no result

More detail

The line with '|| false' in the code is completely redundant and should make no logical difference to the query (if I understand SPARQL correctly). However that is the line that is causing the problem. If I remove that line the query returns the expected result whether the reasoner is on or off. If I add that line then the query only returns results when the reasoner is off but no results when the reasoner is on.

This is an artificial example to illustrate and reproduce the problem but in the real case, instead of '|| false' I have real statements combined with logical or operators and sometimes they are false and I get missing results that should be present.

You mention the "line with || false". Can you share the complete query which is returning expected results?

Hi Jess. The exact same query without the '|| false' returns the expected results.

So that would be:

prefix ex: <http://example.com/>
select *
{
    bind(ex:1 as ?s)
    bind(ex:2 as ?o)
    ?s ?p ?o
    filter(
        exists {?s ex:r1 ?o}
    )
}

Ok, thanks for confirming. Can you share the query plan for both? This is done using the stardog query explain command or using "Show Plan" and clicking the "Text" button in Stardog Studio.

Ah, well therein lies another clue (I think). I noticed that I get an exception when I try to view the explain plan for the query that doesn't give the expected result (with false and reasoner on).

Here are the query plans for the 4 combinations (reasoner on and off and 'false' statement present or not)

no false, reasoner off:

prefix ex: <http://example.com/>

From local
Projection(?s, ?o, ?p) [#1]
`─ MergeJoin(?o) [#1]
   +─ Bind(<http://example.com/1> AS ?s) (<http://example.com/2> AS ?o) [#1]
   │  `─ Scan[OSPC](ex:1, ?p, ex:2) [#1]
   `─ Distinct [#1]
      `─ Scan[POSC](?s, ex:r1, ?o) [#1]

no false, reasoner on:

prefix ex: <http://example.com/>

From local
Distinct [#10]
`─ Projection(?s, ?o, ?p) [#10]
   `─ MergeJoin(?o) [#10]
      +─ Canonicalize(?s, ?o)
      │  `─ Bind(<http://example.com/1> AS ?s) (<http://example.com/2> AS ?o) [#10]
      │     `─ Union [#10]
      │        +─ Property(ex:1, ?p, ex:2-alt)
      │        `─ Property(ex:1, ?p, ex:2)
      `─ Distinct [#1]
         `─ Canonicalize(?s, ?o)
            `─ Scan[POSC](?s, ex:r1, ?o) [#1]

with false, reasoner off:

prefix ex: <http://example.com/>

From local
Projection(?s, ?o, ?p) [#1]
`─ Filter((EXISTS { ?s <http://example.com/r1> ?o . } || "false"^^xsd:boolean)) [#1]
   `─ Bind(<http://example.com/1> AS ?s) (<http://example.com/2> AS ?o) [#1]
      `─ Scan[OSPC](ex:1, ?p, ex:2) [#1]

with false, reasoner on:

000012: com.complexible.stardog.plan.eval.ExecutionException: Cannot render re-written plans

The log file shows more detail about this exception

ERROR 2020-09-26 09:07:22,818 [stardog-user-3] com.complexible.stardog.QueryManager:exceptionTriggered(457): Error during execution of the query
prefix ex: <http://example.com/>
select *
{
    bind(ex:1 as ?s)
    bind(ex:2 as ?o)
    ?s ?p ?o
    filter(
        exists {?s ex:r1 ?o}
        || false
    )
}
with query plan N/A against database rewrite-bug with reasoning schema default
java.lang.RuntimeException: Cannot render re-written plans
        at com.complexible.stardog.plan.util.SPARQLRenderer$Renderer.visit(SPARQLRenderer.java:1110) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.AbstractReasoningPlanNode.accept(AbstractReasoningPlanNode.java:105) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer$Renderer.lambda$visit$6(SPARQLRenderer.java:1071) ~[stardog-7.4.0.jar:?]
        at java.lang.Iterable.forEach(Iterable.java:75) ~[?:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer$Renderer.visit(SPARQLRenderer.java:1071) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.ScopeNodeImpl.accept(ScopeNodeImpl.java:112) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer.renderSelect(SPARQLRenderer.java:183) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer.renderSelect(SPARQLRenderer.java:173) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer$SPARQLExpressionRenderer.visit(SPARQLRenderer.java:1907) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.filter.expr.Exists.accept(Exists.java:101) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer$SPARQLExpressionRenderer.visit(SPARQLRenderer.java:1863) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.filter.expr.Or.accept(Or.java:52) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer$SPARQLExpressionRenderer.toSPARQLString(SPARQLRenderer.java:1764) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer$SPARQLExpressionRenderer.toSPARQLString(SPARQLRenderer.java:1754) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.SPARQLRenderer$SPARQLExpressionRenderer.toSPARQLString(SPARQLRenderer.java:1746) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.ExplainRenderer.visit(ExplainRenderer.java:390) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.FilterPlanNodeImpl.accept(FilterPlanNodeImpl.java:75) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.ExplainRenderer.unaryVisit(ExplainRenderer.java:281) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.ExplainRenderer.visit(ExplainRenderer.java:816) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.ProjectionPlanNodeImpl.accept(ProjectionPlanNodeImpl.java:203) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.ExplainRenderer.unaryVisit(ExplainRenderer.java:281) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.ExplainRenderer.visit(ExplainRenderer.java:760) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.DistinctPlanNodeImpl.accept(DistinctPlanNodeImpl.java:66) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.util.ExplainRenderer.render(ExplainRenderer.java:173) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.eval.ExecutablePlanImpl.explain(ExecutablePlanImpl.java:108) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.plan.eval.QueryEngine.explain(QueryEngine.java:133) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.query.DefaultQueryFactory$AbstractExecutableReadQuery.explain(DefaultQueryFactory.java:289) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.query.DelegatingQuery.explain(DelegatingQuery.java:63) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.query.DelegatingQuery.explain(DelegatingQuery.java:63) ~[stardog-7.4.0.jar:?]
        at com.complexible.stardog.protocols.http.server.SPARQLProtocol.explainQuery(SPARQLProtocol.java:168) ~[stardog-protocols-http-server-7.4.0.jar:?]
        at com.complexible.stardog.protocols.http.server.SPARQLProtocol.explainQueryPost(SPARQLProtocol.java:121) ~[stardog-protocols-http-server-7.4.0.jar:?]
        at com.stardog.http.server.undertow.jaxrs.ExtractRoutes.lambda$handleIt$5(ExtractRoutes.java:192) ~[stardog-protocols-http-server-7.4.0.jar:?]
        at org.apache.shiro.subject.support.SubjectRunnable.doRun(SubjectRunnable.java:120) [shiro-core-1.3.0.jar:1.3.0]
        at org.apache.shiro.subject.support.SubjectRunnable.run(SubjectRunnable.java:108) [shiro-core-1.3.0.jar:1.3.0]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
        at java.lang.Thread.run(Thread.java:834) [?:?]

Oh silly me. I just realized you aren't actually querying anything - there are no triple patterns. Perhaps you wanted ?s ex:r1 ?o outside of the EXISTS filter?

Okay I oversimplified the example too much. So if I add in a triple pattern to the query it still has the same problem (no result when reasoner is on and '|| false' is in the filter). I'll update the original post and the execution plans to include a triple pattern.

Thanks! We'll take a look.

Things are starting to become a little clearer. This (which you had in EXISTS) is the source of at least one of the issues. Can you run explain with reasoning on the query using just this triple pattern alone? select * { ?s ex:r1 ?o }

Hi Jess. Here is the explain plan you requested:

prefix ex: <http://example.com/>

From local
Distinct [#1]
`─ Projection(?s, ?o) [#1]
   `─ Canonicalize(?s, ?o)
      `─ Scan[PSOC](?s, ex:r1, ?o) [#1]

Thanks and apologies for the delay. I can reproduce the problem and looking into it now. We'll update the ticket later today.

Cheers,
Pavel

I believe I see the issue. There's indeed a problem with evaluating EXISTS expressions when owl:sameAs is enabled. The reason it works for you without || false is because in that case the optimiser rewrites the FILTER EXISTS into a join. That optimisation doesn't work for complex filters involving EXISTS.

I created an issue to track this (PLAT-1643). Meanwhile your only workaround would be to avoid EXISTS whenever possible (depends on what else you've got in your filters).

Thanks for the concise bug report, appreciate it,
Pavel