I'm trying approach 3/.

What happens to the CONSTRUCT template though?

The original query:

PREFIX  spin: <http://spinrdf.org/spin#>

CONSTRUCT
  {
    _:c0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
spin:ConstraintViolation .
    _:c0 spin:violationRoot ?this .
    _:c0 spin:violationPath <http://example.com/constrained-predicate> .
    _:c0 spin:violationValue ?object .
  }
WHERE
  { FILTER NOT EXISTS { ?this
<http://example.com/constrained-predicate>  ?object } }

Applied transformation this => http://localhost:8085/default-subject-post

    query = QueryTransformOps.transformQuery(query,
Collections.singletonMap("this",
ResourceFactory.create("http://localhost:8085/default-subject-post";)));

Resulting query:

PREFIX  spin: <http://spinrdf.org/spin#>

CONSTRUCT
  {
    _:c0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
spin:ConstraintViolation .
    _:c0 spin:violationRoot ?this .
    _:c0 spin:violationPath <http://example.com/constrained-predicate> .
    _:c0 spin:violationValue ?object .
  }
WHERE
  { FILTER NOT EXISTS { <http://localhost:8085/default-subject-post>

<http://example.com/constrained-predicate>  ?object
                      }
  }

?this mapping is present in WHERE but gets lost in the template, and
produces no triples during execution. Which is not the case using
initialBinding. Is that expected? Does not really address my use case
then.

On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <a...@apache.org> wrote:
>
> <_:label> is a syntax feature, not built into the storage or query
> execution.
>
> model.createResource("_:" + id));
>
> creates a resource with a strange URI (which is actually illegal by RFC
> 3986/7).
>
> There are various ways:
>
> 1/ The app can put the bnode into the QSM and injected at execution - it
> won't become a bnode-variable because that happens in parsing.
>
> 2/ To put a concrete node into a query:
>
> String bn = "<_:" + id+">";
>
> then put string into SPARQL syntax:
>
> QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
> QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
>
> 3/ rewrite the abstract syntax after parsing:
>
> Map<String, Resource> substitutions =
>    Collections.singletonMap("s", bnode);
> query = QueryFactory.create("SELECT * { ?s ?p ?o }");
> query = QueryTransformOps.transformQuery(query, substitutions);
>
> Forms 2 and 3 have the advantage of not relying on how execution works -
> QSMs are ingested inthe start of execution and e.g. aren't visible in
> subqueries and also interact and bypass with query optimization.
>
>      Andy
>
> On 05/07/2020 15:22, Martynas Jusevičius wrote:
> > Hi,
> >
> > I came across a situation where I want to carry over a blank node ID
> > in a QuerySolutionMap to QueryExecution, to match exact blank node
> > resources rather than have them as variables.
> >
> > I found an old thread by Holger on this topic:
> > https://mail-archives.apache.org/mod_mbox/jena-users/201308.mbox/browser
> >
> > The suggestion was to use <_:LABEL> URI scheme for blank nodes.
> > https://jena.apache.org/documentation/query/extension.html#blank-node-labels
> >
> > Based on that, I tried this logic:
> >
> >      if (instance.isURIResource()) qsm.add(SPIN.THIS_VAR_NAME, instance);
> >      if (instance.isAnon()) qsm.add(SPIN.THIS_VAR_NAME,
> > model.createResource("_:" + instance.getId()));
> >
> > However I'm not getting the results I expect. So I decided to make an
> > isolated test:
> >
> >      @Test
> >      public void bnodeQueryTest()
> >      {
> >          Model model = ModelFactory.createDefaultModel();
> >          Resource bnode = model.createResource().addProperty(FOAF.name,
> > "whateverest");
> >          AnonId id = bnode.getId();
> >
> >          Query query = QueryFactory.create("SELECT * { ?s ?p ?o }");
> >          QuerySolutionMap qsm = new QuerySolutionMap();
> >          qsm.add("s", model.createResource("_:" + id));
> >
> >          try (QueryExecution qex = QueryExecutionFactory.create(query,
> > model, qsm))
> >          {
> >              ResultSet resultSet = qex.execSelect();
> >
> >              assertTrue(resultSet.hasNext());
> >              assertEquals(id, 
> > resultSet.next().get("s").asResource().getId());
> >          }
> >      }
> >
> > The test fails on assertTrue() because SELECT returns no results.
> >
> > Is the test flawed? Am I misunderstanding the use of this URI scheme?
> > If not, what's the purpose if it cannot match blank nodes in data?
> >
> > Martynas
> >

Reply via email to