You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jena.apache.org by Martynas Jusevičius <ma...@atomgraph.com> on 2020/07/05 14:22:29 UTC
Blank node URI scheme
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
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
Missed the BIND(?minCount AS ?mc) FILTER bound(?mc) suggestion, will try it now.
On Mon, Jul 6, 2020 at 12:56 PM Martynas Jusevičius
<ma...@atomgraph.com> wrote:
>
> Andy,
>
> This is getting quite complicated compared to the QuerySolutionMap. I
> get that we should rather be using alternatives, but you presented
> several and neither is a drop-in replacement for the QuerySolutionMap.
> I think Jena's documentation could use a section on this topic, with a
> comparison of the approaches and some criteria which should be used
> when, plus code examples.
>
> I am trying to build a VALUES block now. My code:
>
> Map<String, RDFNode> subs = ...
> Query query = QueryFactory.create(wrapper.getQuery().toString());
> // can't use wrapper.getQuery().cloneQuery() due to JENA-1935
> List<Var> variables = subs.entrySet().stream().map(e ->
> Var.alloc(e.getKey())).collect(Collectors.toList());
> List<Binding> values = subs.entrySet().stream().map(e ->
> BindingFactory.binding(Var.alloc(e.getKey()),
> e.getValue().asNode())).collect(Collectors.toList());
> query.setValuesDataBlock(variables, values);
>
> First of all I am wondering why a substitution map
>
> [( ?predicate = <http://spinrdf.org/spin#body> ), ( ?comment =
> "the body of the Template" ), ( ?minCount = 0 ), ( ?maxCount = 1 )]
>
> produces the VALUES table of the form
>
> VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
> ( spin:body UNDEF UNDEF UNDEF )
> ( UNDEF "the body of the Template" UNDEF UNDEF )
> ( UNDEF UNDEF 0 UNDEF )
> ( UNDEF UNDEF UNDEF 1 )
> }
>
> and not simply
>
> VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
> ( spin:body "the body of the Template" 0 1 )
> }
>
>
> And then what do I do with expressions like FILTER (bound(?maxCount))
> which are used in SPIN's internal queries to "switch off" graph
> patterns (as I understand it) in the absence of the ?maxCount binding.
> It does not seem to have the same effect with VALUES.
>
>
>
>
> On Mon, Jul 6, 2020 at 11:28 AM Andy Seaborne <an...@apache.org> wrote:
> >
> > "bound()" is not a function in the strict sense.
> >
> > Another case where variables are necessary is "AS ?var"
> >
> > Long version:
> > https://afs.github.io/substitute.html
> >
> > The advantage of using VALUES or BIND to inject the substitution value
> > is that it preserves the original variable.
> >
> > Contrast the difference between these two:
> >
> > QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
> > QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
> >
> > BIND(?minCount AS ?mc) FILTER bound(?mc)
> >
> > Andy
> >
> > On 06/07/2020 09:56, Martynas Jusevičius wrote:
> > > The same problem (invalid query string) using
> > > QueryTransformOps.transformQuery().
> > >
> > > On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
> > > <ma...@atomgraph.com> wrote:
> > >>
> > >> ParameterizedSparqlString does not work either (not related to bnodes).
> > >>
> > >> With a mapping ?minCount => 0, it produces an invalid query string:
> > >>
> > >> SELECT (count(*) AS ?cardinality)
> > >> WHERE
> > >> { <http://spinrdf.org/spin#Templates>
> > >> <http://spinrdf.org/spin#body> ?value
> > >> FILTER bound(0)
> > >> }
> > >> HAVING ( ?cardinality < 0 )
> > >>
> > >> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
> > >>>
> > >>>
> > >>>
> > >>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
> > >>>> Thanks for the explanation.
> > >>>>
> > >>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
> > >>>
> > >>> initialBinding is done by making the starting condition for execution a
> > >>> binding of the variables instead of the empty root. (This works nearly
> > >>> always but is affected by variable name scopes - scopes, like subquery,
> > >>> didn't exist when the mechanism was introduced.
> > >>>
> > >>> ParameterizedSparqlString builds which is parsed so you should be able
> > >>> to put in <_:....>.
> > >>>
> > >>> Andy
> > >>>
> > >>>>
> > >>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
> > >>>>>>
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
Thanks, this seems to do the trick:
List<Var> variables = subs.entrySet().stream().map(e ->
Var.alloc(e.getKey())).collect(Collectors.toList());
BindingMap bindingMap = BindingFactory.create();
subs.entrySet().stream().forEach(e ->
bindingMap.add(Var.alloc(e.getKey()), e.getValue().asNode()));
List<Binding> values = Arrays.asList(bindingMap);
query.setValuesDataBlock(variables, values);
On Mon, Jul 6, 2020 at 3:45 PM Andy Seaborne <an...@apache.org> wrote:
>
>
>
> On 06/07/2020 11:56, Martynas Jusevičius wrote:
> > Andy,
> >
> > This is getting quite complicated compared to the QuerySolutionMap. I
> > get that we should rather be using alternatives, but you presented
> > several and neither is a drop-in replacement for the QuerySolutionMap.
> > I think Jena's documentation could use a section on this topic, with a
> > comparison of the approaches and some criteria which should be used
> > when, plus code examples.
> >
> > I am trying to build a VALUES block now. My code:
> >
> > Map<String, RDFNode> subs = ...
> > Query query = QueryFactory.create(wrapper.getQuery().toString());
> > // can't use wrapper.getQuery().cloneQuery() due to JENA-1935
> > List<Var> variables = subs.entrySet().stream().map(e ->
> > Var.alloc(e.getKey())).collect(Collectors.toList());
>
>
> > List<Binding> values = subs.entrySet().stream().map(e ->
> > BindingFactory.binding(Var.alloc(e.getKey()),
> > e.getValue().asNode())).collect(Collectors.toList());
>
> That produces a new binding for key in the map, which is why you the stripe.
>
> Create one binding, add each key/value to the binding.
>
> > query.setValuesDataBlock(variables, values);
> >
> > First of all I am wondering why a substitution map
> >
> > [( ?predicate = <http://spinrdf.org/spin#body> ), ( ?comment =
> > "the body of the Template" ), ( ?minCount = 0 ), ( ?maxCount = 1 )]
> >
> > produces the VALUES table of the form
> >
> > VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
> > ( spin:body UNDEF UNDEF UNDEF )
> > ( UNDEF "the body of the Template" UNDEF UNDEF )
> > ( UNDEF UNDEF 0 UNDEF )
> > ( UNDEF UNDEF UNDEF 1 )
> > }
> >
> > and not simply
> >
> > VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
> > ( spin:body "the body of the Template" 0 1 )
> > }
> >
> >
> > And then what do I do with expressions like FILTER (bound(?maxCount))
> > which are used in SPIN's internal queries to "switch off" graph
> > patterns (as I understand it) in the absence of the ?maxCount binding.
> > It does not seem to have the same effect with VALUES.
> >
> >
> >
> >
> > On Mon, Jul 6, 2020 at 11:28 AM Andy Seaborne <an...@apache.org> wrote:
> >>
> >> "bound()" is not a function in the strict sense.
> >>
> >> Another case where variables are necessary is "AS ?var"
> >>
> >> Long version:
> >> https://afs.github.io/substitute.html
> >>
> >> The advantage of using VALUES or BIND to inject the substitution value
> >> is that it preserves the original variable.
> >>
> >> Contrast the difference between these two:
> >>
> >> QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
> >> QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
> >>
> >> BIND(?minCount AS ?mc) FILTER bound(?mc)
> >>
> >> Andy
> >>
> >> On 06/07/2020 09:56, Martynas Jusevičius wrote:
> >>> The same problem (invalid query string) using
> >>> QueryTransformOps.transformQuery().
> >>>
> >>> On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
> >>> <ma...@atomgraph.com> wrote:
> >>>>
> >>>> ParameterizedSparqlString does not work either (not related to bnodes).
> >>>>
> >>>> With a mapping ?minCount => 0, it produces an invalid query string:
> >>>>
> >>>> SELECT (count(*) AS ?cardinality)
> >>>> WHERE
> >>>> { <http://spinrdf.org/spin#Templates>
> >>>> <http://spinrdf.org/spin#body> ?value
> >>>> FILTER bound(0)
> >>>> }
> >>>> HAVING ( ?cardinality < 0 )
> >>>>
> >>>> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
> >>>>>
> >>>>>
> >>>>>
> >>>>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
> >>>>>> Thanks for the explanation.
> >>>>>>
> >>>>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
> >>>>>
> >>>>> initialBinding is done by making the starting condition for execution a
> >>>>> binding of the variables instead of the empty root. (This works nearly
> >>>>> always but is affected by variable name scopes - scopes, like subquery,
> >>>>> didn't exist when the mechanism was introduced.
> >>>>>
> >>>>> ParameterizedSparqlString builds which is parsed so you should be able
> >>>>> to put in <_:....>.
> >>>>>
> >>>>> Andy
> >>>>>
> >>>>>>
> >>>>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
> >>>>>>>>
Re: Blank node URI scheme
Posted by Andy Seaborne <an...@apache.org>.
On 06/07/2020 11:56, Martynas Jusevičius wrote:
> Andy,
>
> This is getting quite complicated compared to the QuerySolutionMap. I
> get that we should rather be using alternatives, but you presented
> several and neither is a drop-in replacement for the QuerySolutionMap.
> I think Jena's documentation could use a section on this topic, with a
> comparison of the approaches and some criteria which should be used
> when, plus code examples.
>
> I am trying to build a VALUES block now. My code:
>
> Map<String, RDFNode> subs = ...
> Query query = QueryFactory.create(wrapper.getQuery().toString());
> // can't use wrapper.getQuery().cloneQuery() due to JENA-1935
> List<Var> variables = subs.entrySet().stream().map(e ->
> Var.alloc(e.getKey())).collect(Collectors.toList());
> List<Binding> values = subs.entrySet().stream().map(e ->
> BindingFactory.binding(Var.alloc(e.getKey()),
> e.getValue().asNode())).collect(Collectors.toList());
That produces a new binding for key in the map, which is why you the stripe.
Create one binding, add each key/value to the binding.
> query.setValuesDataBlock(variables, values);
>
> First of all I am wondering why a substitution map
>
> [( ?predicate = <http://spinrdf.org/spin#body> ), ( ?comment =
> "the body of the Template" ), ( ?minCount = 0 ), ( ?maxCount = 1 )]
>
> produces the VALUES table of the form
>
> VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
> ( spin:body UNDEF UNDEF UNDEF )
> ( UNDEF "the body of the Template" UNDEF UNDEF )
> ( UNDEF UNDEF 0 UNDEF )
> ( UNDEF UNDEF UNDEF 1 )
> }
>
> and not simply
>
> VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
> ( spin:body "the body of the Template" 0 1 )
> }
>
>
> And then what do I do with expressions like FILTER (bound(?maxCount))
> which are used in SPIN's internal queries to "switch off" graph
> patterns (as I understand it) in the absence of the ?maxCount binding.
> It does not seem to have the same effect with VALUES.
>
>
>
>
> On Mon, Jul 6, 2020 at 11:28 AM Andy Seaborne <an...@apache.org> wrote:
>>
>> "bound()" is not a function in the strict sense.
>>
>> Another case where variables are necessary is "AS ?var"
>>
>> Long version:
>> https://afs.github.io/substitute.html
>>
>> The advantage of using VALUES or BIND to inject the substitution value
>> is that it preserves the original variable.
>>
>> Contrast the difference between these two:
>>
>> QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
>> QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
>>
>> BIND(?minCount AS ?mc) FILTER bound(?mc)
>>
>> Andy
>>
>> On 06/07/2020 09:56, Martynas Jusevičius wrote:
>>> The same problem (invalid query string) using
>>> QueryTransformOps.transformQuery().
>>>
>>> On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
>>> <ma...@atomgraph.com> wrote:
>>>>
>>>> ParameterizedSparqlString does not work either (not related to bnodes).
>>>>
>>>> With a mapping ?minCount => 0, it produces an invalid query string:
>>>>
>>>> SELECT (count(*) AS ?cardinality)
>>>> WHERE
>>>> { <http://spinrdf.org/spin#Templates>
>>>> <http://spinrdf.org/spin#body> ?value
>>>> FILTER bound(0)
>>>> }
>>>> HAVING ( ?cardinality < 0 )
>>>>
>>>> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
>>>>>> Thanks for the explanation.
>>>>>>
>>>>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
>>>>>
>>>>> initialBinding is done by making the starting condition for execution a
>>>>> binding of the variables instead of the empty root. (This works nearly
>>>>> always but is affected by variable name scopes - scopes, like subquery,
>>>>> didn't exist when the mechanism was introduced.
>>>>>
>>>>> ParameterizedSparqlString builds which is parsed so you should be able
>>>>> to put in <_:....>.
>>>>>
>>>>> Andy
>>>>>
>>>>>>
>>>>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
>>>>>>>>
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
Andy,
This is getting quite complicated compared to the QuerySolutionMap. I
get that we should rather be using alternatives, but you presented
several and neither is a drop-in replacement for the QuerySolutionMap.
I think Jena's documentation could use a section on this topic, with a
comparison of the approaches and some criteria which should be used
when, plus code examples.
I am trying to build a VALUES block now. My code:
Map<String, RDFNode> subs = ...
Query query = QueryFactory.create(wrapper.getQuery().toString());
// can't use wrapper.getQuery().cloneQuery() due to JENA-1935
List<Var> variables = subs.entrySet().stream().map(e ->
Var.alloc(e.getKey())).collect(Collectors.toList());
List<Binding> values = subs.entrySet().stream().map(e ->
BindingFactory.binding(Var.alloc(e.getKey()),
e.getValue().asNode())).collect(Collectors.toList());
query.setValuesDataBlock(variables, values);
First of all I am wondering why a substitution map
[( ?predicate = <http://spinrdf.org/spin#body> ), ( ?comment =
"the body of the Template" ), ( ?minCount = 0 ), ( ?maxCount = 1 )]
produces the VALUES table of the form
VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
( spin:body UNDEF UNDEF UNDEF )
( UNDEF "the body of the Template" UNDEF UNDEF )
( UNDEF UNDEF 0 UNDEF )
( UNDEF UNDEF UNDEF 1 )
}
and not simply
VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
( spin:body "the body of the Template" 0 1 )
}
And then what do I do with expressions like FILTER (bound(?maxCount))
which are used in SPIN's internal queries to "switch off" graph
patterns (as I understand it) in the absence of the ?maxCount binding.
It does not seem to have the same effect with VALUES.
On Mon, Jul 6, 2020 at 11:28 AM Andy Seaborne <an...@apache.org> wrote:
>
> "bound()" is not a function in the strict sense.
>
> Another case where variables are necessary is "AS ?var"
>
> Long version:
> https://afs.github.io/substitute.html
>
> The advantage of using VALUES or BIND to inject the substitution value
> is that it preserves the original variable.
>
> Contrast the difference between these two:
>
> QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
> QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
>
> BIND(?minCount AS ?mc) FILTER bound(?mc)
>
> Andy
>
> On 06/07/2020 09:56, Martynas Jusevičius wrote:
> > The same problem (invalid query string) using
> > QueryTransformOps.transformQuery().
> >
> > On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
> > <ma...@atomgraph.com> wrote:
> >>
> >> ParameterizedSparqlString does not work either (not related to bnodes).
> >>
> >> With a mapping ?minCount => 0, it produces an invalid query string:
> >>
> >> SELECT (count(*) AS ?cardinality)
> >> WHERE
> >> { <http://spinrdf.org/spin#Templates>
> >> <http://spinrdf.org/spin#body> ?value
> >> FILTER bound(0)
> >> }
> >> HAVING ( ?cardinality < 0 )
> >>
> >> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
> >>>
> >>>
> >>>
> >>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
> >>>> Thanks for the explanation.
> >>>>
> >>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
> >>>
> >>> initialBinding is done by making the starting condition for execution a
> >>> binding of the variables instead of the empty root. (This works nearly
> >>> always but is affected by variable name scopes - scopes, like subquery,
> >>> didn't exist when the mechanism was introduced.
> >>>
> >>> ParameterizedSparqlString builds which is parsed so you should be able
> >>> to put in <_:....>.
> >>>
> >>> Andy
> >>>
> >>>>
> >>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
> >>>>>>
Re: Blank node URI scheme
Posted by Andy Seaborne <an...@apache.org>.
The restriction on BOUND(?var) is done as a syntax restriction.
Internally, BOUND(constant) is possible and is true (it's a variable
replaced so it is true) and will execute.
See JENA-1044.
On 06/07/2020 15:39, Martynas Jusevičius wrote:
> As I'm reading the spec, bound() is used with variables:
> https://www.w3.org/TR/sparql11-query/#func-bound
>
> However QueryTransformOps.transformQuery() produces a query that looks
> like this:
>
> SELECT *
> WHERE
> { <http://data/instance>
> <http://xmlns.com/foaf/0.1/maker> ?value
> FILTER bound(1)
> }
>
> Which is invalid syntax in principle, but does execute successfully
> using execSelect().
>
> How should that be interpreted?
>
> On Mon, Jul 6, 2020 at 11:28 AM Andy Seaborne <an...@apache.org> wrote:
>>
>> "bound()" is not a function in the strict sense.
>>
>> Another case where variables are necessary is "AS ?var"
>>
>> Long version:
>> https://afs.github.io/substitute.html
>>
>> The advantage of using VALUES or BIND to inject the substitution value
>> is that it preserves the original variable.
>>
>> Contrast the difference between these two:
>>
>> QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
>> QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
>>
>> BIND(?minCount AS ?mc) FILTER bound(?mc)
>>
>> Andy
>>
>> On 06/07/2020 09:56, Martynas Jusevičius wrote:
>>> The same problem (invalid query string) using
>>> QueryTransformOps.transformQuery().
>>>
>>> On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
>>> <ma...@atomgraph.com> wrote:
>>>>
>>>> ParameterizedSparqlString does not work either (not related to bnodes).
>>>>
>>>> With a mapping ?minCount => 0, it produces an invalid query string:
>>>>
>>>> SELECT (count(*) AS ?cardinality)
>>>> WHERE
>>>> { <http://spinrdf.org/spin#Templates>
>>>> <http://spinrdf.org/spin#body> ?value
>>>> FILTER bound(0)
>>>> }
>>>> HAVING ( ?cardinality < 0 )
>>>>
>>>> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
>>>>>> Thanks for the explanation.
>>>>>>
>>>>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
>>>>>
>>>>> initialBinding is done by making the starting condition for execution a
>>>>> binding of the variables instead of the empty root. (This works nearly
>>>>> always but is affected by variable name scopes - scopes, like subquery,
>>>>> didn't exist when the mechanism was introduced.
>>>>>
>>>>> ParameterizedSparqlString builds which is parsed so you should be able
>>>>> to put in <_:....>.
>>>>>
>>>>> Andy
>>>>>
>>>>>>
>>>>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
>>>>>>>>
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
As I'm reading the spec, bound() is used with variables:
https://www.w3.org/TR/sparql11-query/#func-bound
However QueryTransformOps.transformQuery() produces a query that looks
like this:
SELECT *
WHERE
{ <http://data/instance>
<http://xmlns.com/foaf/0.1/maker> ?value
FILTER bound(1)
}
Which is invalid syntax in principle, but does execute successfully
using execSelect().
How should that be interpreted?
On Mon, Jul 6, 2020 at 11:28 AM Andy Seaborne <an...@apache.org> wrote:
>
> "bound()" is not a function in the strict sense.
>
> Another case where variables are necessary is "AS ?var"
>
> Long version:
> https://afs.github.io/substitute.html
>
> The advantage of using VALUES or BIND to inject the substitution value
> is that it preserves the original variable.
>
> Contrast the difference between these two:
>
> QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
> QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
>
> BIND(?minCount AS ?mc) FILTER bound(?mc)
>
> Andy
>
> On 06/07/2020 09:56, Martynas Jusevičius wrote:
> > The same problem (invalid query string) using
> > QueryTransformOps.transformQuery().
> >
> > On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
> > <ma...@atomgraph.com> wrote:
> >>
> >> ParameterizedSparqlString does not work either (not related to bnodes).
> >>
> >> With a mapping ?minCount => 0, it produces an invalid query string:
> >>
> >> SELECT (count(*) AS ?cardinality)
> >> WHERE
> >> { <http://spinrdf.org/spin#Templates>
> >> <http://spinrdf.org/spin#body> ?value
> >> FILTER bound(0)
> >> }
> >> HAVING ( ?cardinality < 0 )
> >>
> >> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
> >>>
> >>>
> >>>
> >>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
> >>>> Thanks for the explanation.
> >>>>
> >>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
> >>>
> >>> initialBinding is done by making the starting condition for execution a
> >>> binding of the variables instead of the empty root. (This works nearly
> >>> always but is affected by variable name scopes - scopes, like subquery,
> >>> didn't exist when the mechanism was introduced.
> >>>
> >>> ParameterizedSparqlString builds which is parsed so you should be able
> >>> to put in <_:....>.
> >>>
> >>> Andy
> >>>
> >>>>
> >>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
> >>>>>>
Re: Blank node URI scheme
Posted by Andy Seaborne <an...@apache.org>.
"bound()" is not a function in the strict sense.
Another case where variables are necessary is "AS ?var"
Long version:
https://afs.github.io/substitute.html
The advantage of using VALUES or BIND to inject the substitution value
is that it preserves the original variable.
Contrast the difference between these two:
QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
BIND(?minCount AS ?mc) FILTER bound(?mc)
Andy
On 06/07/2020 09:56, Martynas Jusevičius wrote:
> The same problem (invalid query string) using
> QueryTransformOps.transformQuery().
>
> On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
> <ma...@atomgraph.com> wrote:
>>
>> ParameterizedSparqlString does not work either (not related to bnodes).
>>
>> With a mapping ?minCount => 0, it produces an invalid query string:
>>
>> SELECT (count(*) AS ?cardinality)
>> WHERE
>> { <http://spinrdf.org/spin#Templates>
>> <http://spinrdf.org/spin#body> ?value
>> FILTER bound(0)
>> }
>> HAVING ( ?cardinality < 0 )
>>
>> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
>>>
>>>
>>>
>>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
>>>> Thanks for the explanation.
>>>>
>>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
>>>
>>> initialBinding is done by making the starting condition for execution a
>>> binding of the variables instead of the empty root. (This works nearly
>>> always but is affected by variable name scopes - scopes, like subquery,
>>> didn't exist when the mechanism was introduced.
>>>
>>> ParameterizedSparqlString builds which is parsed so you should be able
>>> to put in <_:....>.
>>>
>>> Andy
>>>
>>>>
>>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
>>>>>>
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
The same problem (invalid query string) using
QueryTransformOps.transformQuery().
On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
<ma...@atomgraph.com> wrote:
>
> ParameterizedSparqlString does not work either (not related to bnodes).
>
> With a mapping ?minCount => 0, it produces an invalid query string:
>
> SELECT (count(*) AS ?cardinality)
> WHERE
> { <http://spinrdf.org/spin#Templates>
> <http://spinrdf.org/spin#body> ?value
> FILTER bound(0)
> }
> HAVING ( ?cardinality < 0 )
>
> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
> >
> >
> >
> > On 05/07/2020 20:36, Martynas Jusevičius wrote:
> > > Thanks for the explanation.
> > >
> > > What do you mean with "inject" in 1/? ParameterizedSparqlString?
> >
> > initialBinding is done by making the starting condition for execution a
> > binding of the variables instead of the empty root. (This works nearly
> > always but is affected by variable name scopes - scopes, like subquery,
> > didn't exist when the mechanism was introduced.
> >
> > ParameterizedSparqlString builds which is parsed so you should be able
> > to put in <_:....>.
> >
> > Andy
> >
> > >
> > > On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
> > >>>
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
ParameterizedSparqlString does not work either (not related to bnodes).
With a mapping ?minCount => 0, it produces an invalid query string:
SELECT (count(*) AS ?cardinality)
WHERE
{ <http://spinrdf.org/spin#Templates>
<http://spinrdf.org/spin#body> ?value
FILTER bound(0)
}
HAVING ( ?cardinality < 0 )
On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <an...@apache.org> wrote:
>
>
>
> On 05/07/2020 20:36, Martynas Jusevičius wrote:
> > Thanks for the explanation.
> >
> > What do you mean with "inject" in 1/? ParameterizedSparqlString?
>
> initialBinding is done by making the starting condition for execution a
> binding of the variables instead of the empty root. (This works nearly
> always but is affected by variable name scopes - scopes, like subquery,
> didn't exist when the mechanism was introduced.
>
> ParameterizedSparqlString builds which is parsed so you should be able
> to put in <_:....>.
>
> Andy
>
> >
> > On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
> >>>
Re: Blank node URI scheme
Posted by Andy Seaborne <an...@apache.org>.
On 05/07/2020 20:36, Martynas Jusevičius wrote:
> Thanks for the explanation.
>
> What do you mean with "inject" in 1/? ParameterizedSparqlString?
initialBinding is done by making the starting condition for execution a
binding of the variables instead of the empty root. (This works nearly
always but is affected by variable name scopes - scopes, like subquery,
didn't exist when the mechanism was introduced.
ParameterizedSparqlString builds which is parsed so you should be able
to put in <_:....>.
Andy
>
> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
>>>
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
Thanks for the explanation.
What do you mean with "inject" in 1/? ParameterizedSparqlString?
On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <an...@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
> >
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
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 <an...@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
> >
Re: Blank node URI scheme
Posted by Andy Seaborne <an...@apache.org>.
<_: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
>
Re: Blank node URI scheme
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
Jena version: 3.16.0-SNAPSHOT
On Sun, Jul 5, 2020 at 4:22 PM Martynas Jusevičius
<ma...@atomgraph.com> 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