Skip to content

Commit 01de9bb

Browse files
authored
fix: SPARQL Update inserts into the default graph (#3265)
* fix: the return type of Dataset.parse * fix: SPARQL Update inserts into the default graph does not create a new graph with a blank node label as the graph name * chore: add todo comment
1 parent 2796fee commit 01de9bb

File tree

3 files changed

+93
-4
lines changed

3 files changed

+93
-4
lines changed

rdflib/graph.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2623,7 +2623,7 @@ def parse(
26232623
file: Optional[Union[BinaryIO, TextIO]] = None,
26242624
data: Optional[Union[str, bytes]] = None,
26252625
**args: Any,
2626-
) -> Graph:
2626+
) -> Dataset:
26272627
"""
26282628
Parse an RDF source adding the resulting triples to the Graph.
26292629

rdflib/plugins/sparql/update.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ def evalModify(ctx: QueryContext, u: CompValue) -> None:
182182
ctx = ctx.pushGraph(g)
183183

184184
for c in list(res):
185-
dg = ctx.graph
185+
# TODO: Make this more intentional and without the weird type checking logic
186+
# once ConjunctiveGraph is removed and Dataset no longer inherits from
187+
# Graph.
188+
dg = ctx.graph if type(ctx.graph) is Graph else ctx.dataset.default_context
186189
if u.delete:
187190
# type error: Unsupported left operand type for - ("None")
188191
# type error: Unsupported operand types for - ("Graph" and "Generator[Tuple[Identifier, Identifier, Identifier], None, None]")

test/test_sparql/test_update.py

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
import pytest
66

7-
from rdflib import Literal, Namespace, Variable
8-
from rdflib.graph import ConjunctiveGraph, Dataset, Graph
7+
from rdflib import Literal, Namespace, URIRef, Variable
8+
from rdflib.compare import isomorphic
9+
from rdflib.graph import DATASET_DEFAULT_GRAPH_ID, ConjunctiveGraph, Dataset, Graph
910
from test.data import TEST_DATA_DIR
1011
from test.utils import GraphHelper
1112
from test.utils.graph import GraphSource
@@ -164,3 +165,88 @@ def test_reevaluation_between_updates_insert() -> None:
164165
result = g.query("SELECT ?x WHERE { ex:bar ex:value ?x }")
165166
values = {b.get(Variable("x")) for b in result} # type: ignore
166167
assert values == {Literal(3), Literal(4), Literal(14)}
168+
169+
170+
def test_inserts_in_named_graph():
171+
trig_data = """
172+
@prefix ex: <http://example.org/> .
173+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
174+
175+
# Named graph 1
176+
ex:graph1 {
177+
ex:person1 ex:name "Alice" ;
178+
ex:age 30 .
179+
}
180+
181+
# Named graph 2
182+
ex:graph2 {
183+
ex:person1 ex:worksFor ex:company1 .
184+
ex:company1 ex:industry "Technology" .
185+
}
186+
"""
187+
ds = Dataset().parse(data=trig_data, format="trig")
188+
ds.update(
189+
"""
190+
INSERT {
191+
GRAPH <urn:graph> {
192+
?s ?p ?o
193+
}
194+
195+
?s ?p ?o
196+
}
197+
WHERE {
198+
GRAPH ?g {
199+
?s ?p ?o
200+
}
201+
}
202+
"""
203+
)
204+
205+
expected_trig = """
206+
@prefix ex: <http://example.org/> .
207+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
208+
209+
{
210+
ex:person1 ex:age 30 ;
211+
ex:name "Alice" ;
212+
ex:worksFor ex:company1 .
213+
214+
ex:company1 ex:industry "Technology" .
215+
}
216+
217+
<urn:graph> {
218+
ex:person1 ex:age 30 ;
219+
ex:name "Alice" ;
220+
ex:worksFor ex:company1 .
221+
222+
ex:company1 ex:industry "Technology" .
223+
}
224+
225+
ex:graph1 {
226+
ex:person1 ex:age 30 ;
227+
ex:name "Alice" .
228+
}
229+
230+
ex:graph2 {
231+
ex:person1 ex:worksFor ex:company1 .
232+
233+
ex:company1 ex:industry "Technology" .
234+
}
235+
"""
236+
expected_ds = Dataset().parse(data=expected_trig, format="trig")
237+
238+
# There should be exactly 4 graphs, including the default graph.
239+
# SPARQL Update inserts into the default graph should go into the default graph,
240+
# not to a new graph with a blank node label.
241+
# See https://github.com/RDFLib/rdflib/issues/3080
242+
expected_graph_names = [
243+
DATASET_DEFAULT_GRAPH_ID,
244+
URIRef("urn:graph"),
245+
URIRef("http://example.org/graph1"),
246+
URIRef("http://example.org/graph2"),
247+
]
248+
assert set(expected_graph_names) == set(graph.identifier for graph in ds.graphs())
249+
250+
for graph in ds.graphs():
251+
expected_graph = expected_ds.graph(graph.identifier)
252+
assert isomorphic(graph, expected_graph)

0 commit comments

Comments
 (0)