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 <a...@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
<marty...@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 <a...@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 <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