Skip to content

Using FROM and FROM NAMED on ConjunctiveGraph behaves not standard conform #811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
white-gecko opened this issue Feb 22, 2018 · 4 comments
Labels

Comments

@white-gecko
Copy link
Member

I want to use FROM and FROM NAMED in a SPARQL query to select the default graph resp. named graphs to execute the query on. But the RDFlib implementation does not act as it is described in the SPARQL 1.1 specification especially the section "13.2 Specifying RDF Datasets" (https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#specifyingDataset)

To demonstrate this behavior, I've created an MWE:

#!/usr/bin/env python3

import rdflib.plugins.sparql
from rdflib import ConjunctiveGraph
 
data = """
<urn:a> <urn:a> <urn:a> <urn:a> .
<urn:b> <urn:b> <urn:b> <urn:b> .
<urn:c> <urn:c> <urn:c> <urn:c> .
"""

if __name__ == "__main__":
    rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = False  # Line A
    rdflib.plugins.sparql.SPARQL_LOAD_GRAPHS = False
    graph = ConjunctiveGraph()
    graph.parse(data=data, format='nquads')
    result = graph.query("SELECT * {?s ?p ?o}")               # Line B
    for resrow in result:
        print(resrow)

Running this code behaves as expected, while I will show derived examples in the following, by altering Line A and Line B:

1. Replacing the Default Graph

rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = True       # Line A
result = graph.query("SELECT * FROM <urn:b> {?s ?p ?o}")      # Line B
  • What I see: returns all three statements.
  • What I expect: Only the statement <urn:b> <urn:b> <urn:b> as result
  • Why is the actual result not correct?:

A SPARQL query may specify the dataset to be used for matching by using the FROM clause and the FROM NAMED clause to describe the RDF dataset. If a query provides such a dataset description, then it is used in place of any dataset that the query service would use if no dataset description is provided in a query.
(https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#specifyingDataset)

2. Specifying a Named Graph but Querying the Default Gaph

rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = True         # Line A
result = graph.query("SELECT * FROM NAMED <urn:b> { ?s ?p ?o}") # Line B
  • What I see: returns all three statements.
  • What I expect: no result
  • Why is the actual result not correct?:

If there is no FROM clause, but there is one or more FROM NAMED clauses, then the dataset includes an empty graph for the default graph.
(https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#specifyingDataset)

3. Specifying a Named Graph

rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = False                   # Line A
result = graph.query("SELECT * FROM NAMED <urn:b> { GRAPH ?g {?s ?p ?o}}") # Line B
  • What I see: returns all three statements.
  • What I expect: Only the statement <urn:b> <urn:b> <urn:b> <urn:b> as result
  • Why is the actual result not correct?: Because this is the idea of NAMED GRAPH to specify a named graph to query.

A query can supply IRIs for the named graphs in the RDF Dataset using the FROM NAMED clause. Each IRI is used to provide one named graph in the RDF Dataset.
(https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#specifyingDataset)

Because I think all of these three cases are related to each other I've put them into one issue, but sure they could also be split into three issues.

@ghost
Copy link

ghost commented Jan 1, 2022

For a while, I thought this might be related to the identifier-as-context changes but now I realise that it's unrelated. fwiw, test included:

import rdflib.plugins.sparql
from rdflib import ConjunctiveGraph


def test_issue811():

    data = """
    <urn:a> <urn:a> <urn:a> <urn:a> .
    <urn:b> <urn:b> <urn:b> <urn:b> .
    <urn:c> <urn:c> <urn:c> <urn:c> .
    """

    rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = False
    rdflib.plugins.sparql.SPARQL_LOAD_GRAPHS = False

    graph = ConjunctiveGraph()
    graph.parse(data=data, format="nquads")
    assert len(graph) == 3

    assert len(graph.query("SELECT * {?s ?p ?o .}")) == 0

    # Set default graph as UNION, CORRECT result
    rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = True
    assert len(graph.query("SELECT * {?s ?p ?o .}")) == 3

    # Use FROM to specify <urn:b> as the default graph

    # Set default graph as UNION, INCORRECT result
    rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = True
    assert (
        len(graph.query("SELECT * FROM <urn:b> {?s ?p ?o}")) == 3
    ), "should be 1 triple"

    # Set default graph as NON-UNION, CORRECT result
    rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = False
    assert (
        len(graph.query("SELECT * FROM <urn:b> {?s ?p ?o}")) == 1
    ), "should be 1 triple"

    # Use FROM NAMED to specify <urn:b> as target graph

    # Set default graph as UNION, INCORRECT result
    rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = True
    assert (
        len(graph.query("SELECT * FROM NAMED <urn:b> {?s ?p ?o}")) == 3
    ), "should be 1 triple"

    # Set default graph as NON-UNION, CORRECT result
    rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION = False
    assert (
        len(graph.query("SELECT * FROM NAMED <urn:b> {?s ?p ?o}")) == 1
    ), "should be 1 triple"

@aucampia
Copy link
Member

aucampia commented Jan 1, 2022

will add with xfail if I have time

@aucampia
Copy link
Member

@apicouSP
Copy link
Contributor

Since the issue still doesn't have a fix, I made one:
For the moment, just for the queries, it would still be necessary to manage update USING/USING NAMED clauses.
What I implemented:
Include only the graphs in FROM clause in the query's default graph
Include only the graphs in the FROM NAMED clause in the query's named graphs

And also:
Try to load external graphs only if they don't already exist in the given ConjunctiveGraph

In my understanding of the w3c spec, if we define a FROM clause, the query's RDF dataset is considered explicit, and if there is no FROM NAMED clause, then named graph is considered empty set. And vice versa. That is what I implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants