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 2024/11/26 08:56:03 UTC
VALUES not passed to SERVICE in federated queries
Hi,
I have two Fuseki 4.6.1 instances in a Docker network (fuseki-admin
and fuseki-end-user) that federate SPARQL queries between each other.
When I execute this query on fuseki-admin:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX acl: <http://www.w3.org/ns/auth/acl#>
PREFIX sioc: <http://rdfs.org/sioc/ns#>
SELECT *
FROM <urn:x-arq:UnionGraph>
WHERE
{ VALUES ( ?this ?Container ) {
( <https://localhost:4443/whateverest/> <https://localhost:4443/> )
}
SERVICE <http://fuseki-end-user:3030/ds/>
{ GRAPH ?Container
{ ?Container a ?Type }
}
}
then I can see the ?Container binding was injected into the query
string executed on fuseki-end-user:
Query = SELECT * WHERE { GRAPH <https://localhost:4443/> {
<https://localhost:4443/> a ?Type } }
However when I add FILTER NOT EXISTS to the federated part
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX acl: <http://www.w3.org/ns/auth/acl#>
PREFIX sioc: <http://rdfs.org/sioc/ns#>
SELECT *
FROM <urn:x-arq:UnionGraph>
WHERE
{ VALUES (?this ?Container) { (<https://localhost:4443/whateverest/>
<https://localhost:4443/>) }
SERVICE <http://fuseki-end-user:3030/ds/>
{ GRAPH ?Container
{
?Container a ?Type
}
FILTER NOT EXISTS { GRAPH ?this
{ ?this
sioc:has_parent|sioc:has_container ?Container }
}
}
}
I see a single request in fuseki-end-user but none of the variables
are bound to anything:
Query = Query = SELECT * WHERE { GRAPH ?Container {
?Container a ?Type } FILTER NOT EXISTS { GRAPH ?this
{ ?this
<http://rdfs.org/sioc/ns#has_parent>|<http://rdfs.org/sioc/ns#has_container>
?Container }
This looks plain wrong because without bindings it eliminates too many
(positive) results, and the final result on fuseki-end-user comes out
empty.
Is this a bug or am I misunderstanding something about VALUES and/or SERVICE?
Martynas
Re: VALUES not passed to SERVICE in federated queries
Posted by Martynas Jusevičius <ma...@atomgraph.com>.
Correction: "... and the final result on *fuseki-admin* comes out empty."
On Tue, Nov 26, 2024 at 9:56 AM Martynas Jusevičius
<ma...@atomgraph.com> wrote:
>
> Hi,
>
> I have two Fuseki 4.6.1 instances in a Docker network (fuseki-admin
> and fuseki-end-user) that federate SPARQL queries between each other.
>
> When I execute this query on fuseki-admin:
>
> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
> PREFIX acl: <http://www.w3.org/ns/auth/acl#>
> PREFIX sioc: <http://rdfs.org/sioc/ns#>
>
> SELECT *
> FROM <urn:x-arq:UnionGraph>
> WHERE
> { VALUES ( ?this ?Container ) {
> ( <https://localhost:4443/whateverest/> <https://localhost:4443/> )
> }
> SERVICE <http://fuseki-end-user:3030/ds/>
> { GRAPH ?Container
> { ?Container a ?Type }
> }
> }
>
> then I can see the ?Container binding was injected into the query
> string executed on fuseki-end-user:
>
> Query = SELECT * WHERE { GRAPH <https://localhost:4443/> {
> <https://localhost:4443/> a ?Type } }
>
> However when I add FILTER NOT EXISTS to the federated part
>
> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
> PREFIX acl: <http://www.w3.org/ns/auth/acl#>
> PREFIX sioc: <http://rdfs.org/sioc/ns#>
>
> SELECT *
> FROM <urn:x-arq:UnionGraph>
> WHERE
> { VALUES (?this ?Container) { (<https://localhost:4443/whateverest/>
> <https://localhost:4443/>) }
> SERVICE <http://fuseki-end-user:3030/ds/>
> { GRAPH ?Container
> {
> ?Container a ?Type
> }
> FILTER NOT EXISTS { GRAPH ?this
> { ?this
> sioc:has_parent|sioc:has_container ?Container }
> }
> }
> }
>
> I see a single request in fuseki-end-user but none of the variables
> are bound to anything:
>
> Query = Query = SELECT * WHERE { GRAPH ?Container {
> ?Container a ?Type } FILTER NOT EXISTS { GRAPH ?this
> { ?this
> <http://rdfs.org/sioc/ns#has_parent>|<http://rdfs.org/sioc/ns#has_container>
> ?Container }
>
> This looks plain wrong because without bindings it eliminates too many
> (positive) results, and the final result on fuseki-end-user comes out
> empty.
>
> Is this a bug or am I misunderstanding something about VALUES and/or SERVICE?
>
> Martynas
Re: VALUES not passed to SERVICE in federated queries
Posted by Andy Seaborne <an...@apache.org>.
> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
> PREFIX acl: <http://www.w3.org/ns/auth/acl#>
> PREFIX sioc: <http://rdfs.org/sioc/ns#>
>
> SELECT *
> FROM <urn:x-arq:UnionGraph>
> WHERE
> { VALUES ( ?this ?Container ) {
> ( <https://localhost:4443/whateverest/> <https://localhost:4443/> )
> }
> SERVICE <http://fuseki-end-user:3030/ds/>
> { GRAPH ?Container
> { ?Container a ?Type }
> }
> }
For Fuseki-specific solution:
LATERAL may work
WHERE
{ VALUES ( ?this ?Container ) {
( <https://localhost:4443/whateverest/> <https://localhost:4443/> ) }
LATERAL {
SERVICE <http://fuseki-end-user:3030/ds/>
{ GRAPH ?Container
{ ?Container a ?Type }
}
}
}
It's Fuseki-specific (ATM) becuae it needs to rewrite the SERVICE block.
Normally, that's an alegbra rewrite but for SERVICE it needs to recreate
query syntax and it's using LET currently.
Andy
LET is an ARQ extension like BIND except if the variable is already
bound to the same value it passes the soltion, and if it is a different
value does not match. So it is a combination of BIND and FILTER sameTerm
and is position insensitive unlike BIND.
Re: Re: VALUES not passed to SERVICE in federated queries
Posted by Claus Stadler <cs...@informatik.uni-leipzig.de>.
I did a quick successful test with the data and query below.
It wasn't sure whether the service enhancer's substitution approach
would work with FILTER (NOT) EXISTS because IIRC I didn't write tests
for this case, but it seems to work as expected:
Data - One product 'a' with 2 categories, of which cat1 has the feature
f2 which should cause it to be excluded:
```sparql
INSERT DATA {
<urn:a> <urn:hasCategory> <urn:cat1> .
<urn:cat1> <urn:hasFeature> <urn:f1> .
<urn:cat1> <urn:hasFeature> <urn:f2> .
<urn:a> <urn:hasCategory> <urn:cat2> .
<urn:cat2> <urn:hasFeature> <urn:f3> .
<urn:cat2> <urn:hasFeature> <urn:f4> .
}
```
Query using SERVICE <loop:>:
```sparql
SELECT *
WHERE
{
VALUES (?product ?feature) { (<urn:a> <urn:f2>) }
SERVICE <loop:> {
SELECT ?category {
?product <urn:hasCategory> ?category .
FILTER NOT EXISTS { ?category <urn:hasFeature> ?feature }
}
}
}
```
Note, that you can use SERVICE <loop:bulk+N:> to batch N bindings into a
single request.
Output is the 'cat2' which does not have feature 'f2':
```
(?product = <urn:a>, ?feature = <urn:f2>, ?category = <urn:cat2>)
```
The substituted queries ignores the standard scoping rules and thus
looks like:
```sparql
SELECT *
WHERE
{ { { SELECT ?category
WHERE
{ <urn:a> <urn:hasCategory> ?category
FILTER NOT EXISTS { ?category <urn:hasFeature> <urn:f2> }
}
}
BIND(0 AS ?__idx__)
}
UNION
{ BIND(1000000000 AS ?__idx__) }
}
```
As a side note, I have an maintenance update of the service enhancer
plugin in the works with a some smaller fixes and improvements (e.g.
improved cancellation handling based on recent changes I contributed to
ARQ) of the existing system and and hope to have the PR ready during
December.
I will also add FILTER (NOT) EXISTS this test case to the test suite.
Cheers,
Claus
On 27.11.24 20:13, Andy Seaborne wrote:
>
>
> On 26/11/2024 08:56, Martynas Jusevičius wrote:
>> Hi,
>>
>> I have two Fuseki 4.6.1 instances in a Docker network (fuseki-admin
>> and fuseki-end-user) that federate SPARQL queries between each other.
>
> If you want to provide detailed control of SERVICE, then there is
>
> https://jena.apache.org/documentation/query/service_enhancer.html
>
>
>>
>> When I execute this query on fuseki-admin:
>>
>> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
>> PREFIX acl: <http://www.w3.org/ns/auth/acl#>
>> PREFIX sioc: <http://rdfs.org/sioc/ns#>
>>
>> SELECT *
>> FROM <urn:x-arq:UnionGraph>
>> WHERE
>> { VALUES ( ?this ?Container ) {
>> ( <https://localhost:4443/whateverest/>
>> <https://localhost:4443/> )
>> }
>> SERVICE <http://fuseki-end-user:3030/ds/>
>> { GRAPH ?Container
>> { ?Container a ?Type }
>> }
>> }
>>
>> then I can see the ?Container binding was injected into the query
>> string executed on fuseki-end-user:
>>
>> Query = SELECT * WHERE { GRAPH <https://localhost:4443/> {
>> <https://localhost:4443/> a ?Type } }
>>
>> However when I add FILTER NOT EXISTS to the federated part
>>
>> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
>> PREFIX acl: <http://www.w3.org/ns/auth/acl#>
>> PREFIX sioc: <http://rdfs.org/sioc/ns#>
>>
>> SELECT *
>> FROM <urn:x-arq:UnionGraph>
>> WHERE
>> { VALUES (?this ?Container) { (<https://localhost:4443/whateverest/>
>> <https://localhost:4443/>) }
>> SERVICE <http://fuseki-end-user:3030/ds/>
>> { GRAPH ?Container
>> {
>> ?Container a ?Type
>> }
>> FILTER NOT EXISTS { GRAPH ?this
>> { ?this
>> sioc:has_parent|sioc:has_container ?Container }
>> }
>> }
>> }
>
> Without the service enhancer, there is no rewrite and it is a has join:
>
> (join
> VALUES
> SERVICE
> )
>
> otherwise it can become a denial of service vector!
>
> With control such as correlated joins:
> https://jena.apache.org/documentation/query/service_enhancer.html#correlated-joins
>
>
> you may be able to get the effect you want.
>
> The ?this case is changing the meaning of the query -- ?this is not
> in-scope in the NOT EXISTS so it is undefined.
>
> Andy
>
>>
>> I see a single request in fuseki-end-user but none of the variables
>> are bound to anything:
>>
>> Query = Query = SELECT * WHERE { GRAPH ?Container {
>> ?Container a ?Type } FILTER NOT EXISTS { GRAPH ?this
>> { ?this
>> <http://rdfs.org/sioc/ns#has_parent>|<http://rdfs.org/sioc/ns#has_container>
>>
>> ?Container }
>>
>> This looks plain wrong because without bindings it eliminates too many
>> (positive) results, and the final result on fuseki-end-user comes out
>> empty.
>>
>> Is this a bug or am I misunderstanding something about VALUES and/or
>> SERVICE?
>>
>> Martynas
>
Re: VALUES not passed to SERVICE in federated queries
Posted by Andy Seaborne <an...@apache.org>.
On 26/11/2024 08:56, Martynas Jusevičius wrote:
> Hi,
>
> I have two Fuseki 4.6.1 instances in a Docker network (fuseki-admin
> and fuseki-end-user) that federate SPARQL queries between each other.
If you want to provide detailed control of SERVICE, then there is
https://jena.apache.org/documentation/query/service_enhancer.html
>
> When I execute this query on fuseki-admin:
>
> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
> PREFIX acl: <http://www.w3.org/ns/auth/acl#>
> PREFIX sioc: <http://rdfs.org/sioc/ns#>
>
> SELECT *
> FROM <urn:x-arq:UnionGraph>
> WHERE
> { VALUES ( ?this ?Container ) {
> ( <https://localhost:4443/whateverest/> <https://localhost:4443/> )
> }
> SERVICE <http://fuseki-end-user:3030/ds/>
> { GRAPH ?Container
> { ?Container a ?Type }
> }
> }
>
> then I can see the ?Container binding was injected into the query
> string executed on fuseki-end-user:
>
> Query = SELECT * WHERE { GRAPH <https://localhost:4443/> {
> <https://localhost:4443/> a ?Type } }
>
> However when I add FILTER NOT EXISTS to the federated part
>
> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
> PREFIX acl: <http://www.w3.org/ns/auth/acl#>
> PREFIX sioc: <http://rdfs.org/sioc/ns#>
>
> SELECT *
> FROM <urn:x-arq:UnionGraph>
> WHERE
> { VALUES (?this ?Container) { (<https://localhost:4443/whateverest/>
> <https://localhost:4443/>) }
> SERVICE <http://fuseki-end-user:3030/ds/>
> { GRAPH ?Container
> {
> ?Container a ?Type
> }
> FILTER NOT EXISTS { GRAPH ?this
> { ?this
> sioc:has_parent|sioc:has_container ?Container }
> }
> }
> }
Without the service enhancer, there is no rewrite and it is a has join:
(join
VALUES
SERVICE
)
otherwise it can become a denial of service vector!
With control such as correlated joins:
https://jena.apache.org/documentation/query/service_enhancer.html#correlated-joins
you may be able to get the effect you want.
The ?this case is changing the meaning of the query -- ?this is not
in-scope in the NOT EXISTS so it is undefined.
Andy
>
> I see a single request in fuseki-end-user but none of the variables
> are bound to anything:
>
> Query = Query = SELECT * WHERE { GRAPH ?Container {
> ?Container a ?Type } FILTER NOT EXISTS { GRAPH ?this
> { ?this
> <http://rdfs.org/sioc/ns#has_parent>|<http://rdfs.org/sioc/ns#has_container>
> ?Container }
>
> This looks plain wrong because without bindings it eliminates too many
> (positive) results, and the final result on fuseki-end-user comes out
> empty.
>
> Is this a bug or am I misunderstanding something about VALUES and/or SERVICE?
>
> Martynas