0
# SPARQL Queries and Updates
1
2
Complete SPARQL 1.1 implementation supporting SELECT, CONSTRUCT, ASK, DESCRIBE queries and INSERT, DELETE, LOAD, CLEAR updates with extension mechanisms for custom functions.
3
4
## Capabilities
5
6
### Query Preparation and Execution
7
8
Functions for preparing and executing SPARQL queries with namespace bindings and variable bindings.
9
10
```python { .api }
11
def prepareQuery(queryString: str, initNs: Dict[str, Namespace] = None, base: str = None):
12
"""
13
Prepare a SPARQL query for execution.
14
15
Parameters:
16
- queryString: SPARQL query string
17
- initNs: Initial namespace bindings
18
- base: Base URI for relative references
19
20
Returns:
21
PreparedQuery: Prepared query object
22
"""
23
24
def prepareUpdate(updateString: str, initNs: Dict[str, Namespace] = None, base: str = None):
25
"""
26
Prepare a SPARQL update for execution.
27
28
Parameters:
29
- updateString: SPARQL update string
30
- initNs: Initial namespace bindings
31
- base: Base URI for relative references
32
33
Returns:
34
PreparedUpdate: Prepared update object
35
"""
36
```
37
38
### Result - Query Result Container
39
40
Container for SPARQL query results with iteration and serialization capabilities.
41
42
```python { .api }
43
class Result:
44
def __init__(self, type: str):
45
"""
46
Create a result container.
47
48
Parameters:
49
- type: Result type ('SELECT', 'CONSTRUCT', 'ASK', 'DESCRIBE')
50
"""
51
52
def __iter__(self) -> Iterator:
53
"""
54
Iterate over result rows or triples.
55
56
Returns:
57
Iterator: ResultRow objects for SELECT, triples for CONSTRUCT/DESCRIBE
58
"""
59
60
def __len__(self) -> int:
61
"""
62
Get number of results.
63
64
Returns:
65
int: Result count
66
"""
67
68
def __bool__(self) -> bool:
69
"""
70
Boolean conversion (useful for ASK queries).
71
72
Returns:
73
bool: True if results exist or ASK result is true
74
"""
75
76
def serialize(self, format: str = 'xml', encoding: str = 'utf-8') -> str:
77
"""
78
Serialize results to specified format.
79
80
Parameters:
81
- format: Output format ('xml', 'json', 'csv', 'tsv')
82
- encoding: Character encoding
83
84
Returns:
85
str: Serialized results
86
"""
87
88
@property
89
def type(self) -> str:
90
"""
91
Get result type.
92
93
Returns:
94
str: 'SELECT', 'CONSTRUCT', 'ASK', or 'DESCRIBE'
95
"""
96
97
@property
98
def bindings(self) -> List[Dict[str, Node]]:
99
"""
100
Get variable bindings for SELECT results.
101
102
Returns:
103
List: List of binding dictionaries
104
"""
105
106
@property
107
def vars(self) -> List[str]:
108
"""
109
Get query variables for SELECT results.
110
111
Returns:
112
List: Variable names
113
"""
114
115
@property
116
def graph(self) -> Graph:
117
"""
118
Get result graph for CONSTRUCT/DESCRIBE results.
119
120
Returns:
121
Graph: Result graph
122
"""
123
```
124
125
### ResultRow - Individual Result Row
126
127
Individual row from SELECT query results.
128
129
```python { .api }
130
class ResultRow:
131
def __init__(self, values: Dict[str, Node], labels: List[str]):
132
"""
133
Create a result row.
134
135
Parameters:
136
- values: Variable bindings
137
- labels: Variable names
138
"""
139
140
def __getitem__(self, key: Union[str, int]) -> Node:
141
"""
142
Get value by variable name or index.
143
144
Parameters:
145
- key: Variable name or index
146
147
Returns:
148
Node: Bound value
149
"""
150
151
def __getattr__(self, name: str) -> Node:
152
"""
153
Get value by variable name as attribute.
154
155
Parameters:
156
- name: Variable name
157
158
Returns:
159
Node: Bound value
160
"""
161
162
def __iter__(self) -> Iterator[Node]:
163
"""
164
Iterate over bound values.
165
166
Returns:
167
Iterator: Bound values in order
168
"""
169
170
def asdict(self) -> Dict[str, Node]:
171
"""
172
Get row as dictionary.
173
174
Returns:
175
Dict: Variable name to value mapping
176
"""
177
```
178
179
### Processor - Query Processor Interface
180
181
Base interface for SPARQL query processors.
182
183
```python { .api }
184
class Processor:
185
def query(self, query, initBindings: Dict = None, initNs: Dict[str, Namespace] = None, base: str = None, **kwargs) -> Result:
186
"""
187
Execute a SPARQL query.
188
189
Parameters:
190
- query: Query string or prepared query
191
- initBindings: Initial variable bindings
192
- initNs: Initial namespace bindings
193
- base: Base URI
194
195
Returns:
196
Result: Query results
197
"""
198
```
199
200
### UpdateProcessor - Update Processor Interface
201
202
Base interface for SPARQL update processors.
203
204
```python { .api }
205
class UpdateProcessor:
206
def update(self, update, initBindings: Dict = None, initNs: Dict[str, Namespace] = None, base: str = None, **kwargs):
207
"""
208
Execute a SPARQL update.
209
210
Parameters:
211
- update: Update string or prepared update
212
- initBindings: Initial variable bindings
213
- initNs: Initial namespace bindings
214
- base: Base URI
215
"""
216
```
217
218
## Usage Examples
219
220
### SELECT Queries
221
222
```python
223
from rdflib import Graph
224
from rdflib.namespace import FOAF
225
from rdflib.plugins.sparql import prepareQuery
226
227
g = Graph()
228
g.parse("people.ttl", format="turtle")
229
230
# Simple SELECT query
231
query = """
232
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
233
SELECT ?name ?age WHERE {
234
?person foaf:name ?name .
235
?person foaf:age ?age .
236
FILTER(?age > 25)
237
}
238
ORDER BY ?age
239
"""
240
241
results = g.query(query)
242
for row in results:
243
print(f"Name: {row.name}, Age: {row.age}")
244
245
# Access by index
246
for row in results:
247
print(f"Name: {row[0]}, Age: {row[1]}")
248
249
# Convert to dictionary
250
for row in results:
251
data = row.asdict()
252
print(f"Data: {data}")
253
```
254
255
### Prepared Queries
256
257
```python
258
from rdflib import Graph, Literal
259
from rdflib.namespace import FOAF
260
from rdflib.plugins.sparql import prepareQuery
261
262
g = Graph()
263
# ... populate graph ...
264
265
# Prepare query with namespace bindings
266
query_string = """
267
SELECT ?name ?email WHERE {
268
?person foaf:name ?name .
269
?person foaf:mbox ?email .
270
FILTER(?name = ?target_name)
271
}
272
"""
273
274
prepared = prepareQuery(query_string, initNs={"foaf": FOAF})
275
276
# Execute with variable bindings
277
results = g.query(prepared, initBindings={"target_name": Literal("John Doe")})
278
for row in results:
279
print(f"Name: {row.name}, Email: {row.email}")
280
```
281
282
### CONSTRUCT Queries
283
284
```python
285
from rdflib import Graph
286
287
g = Graph()
288
g.parse("full_data.ttl", format="turtle")
289
290
# CONSTRUCT query to extract subset
291
construct_query = """
292
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
293
CONSTRUCT {
294
?person foaf:name ?name .
295
?person foaf:age ?age .
296
}
297
WHERE {
298
?person foaf:name ?name .
299
?person foaf:age ?age .
300
FILTER(?age >= 18)
301
}
302
"""
303
304
result_graph = g.query(construct_query)
305
print(f"Constructed graph has {len(result_graph)} triples")
306
307
# Serialize the result graph
308
adult_data = result_graph.serialize(format="turtle")
309
```
310
311
### ASK Queries
312
313
```python
314
from rdflib import Graph
315
316
g = Graph()
317
g.parse("data.ttl", format="turtle")
318
319
# ASK query to check existence
320
ask_query = """
321
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
322
ASK {
323
?person foaf:name "John Doe" .
324
?person foaf:age ?age .
325
FILTER(?age > 30)
326
}
327
"""
328
329
result = g.query(ask_query)
330
if result:
331
print("Found John Doe over 30")
332
else:
333
print("No match found")
334
335
# Boolean conversion
336
has_match = bool(result)
337
```
338
339
### DESCRIBE Queries
340
341
```python
342
from rdflib import Graph, URIRef
343
344
g = Graph()
345
g.parse("data.ttl", format="turtle")
346
347
# DESCRIBE query
348
describe_query = """
349
DESCRIBE <http://example.org/person/1>
350
"""
351
352
result = g.query(describe_query)
353
described_graph = result.graph
354
355
print(f"Description has {len(described_graph)} triples")
356
for triple in described_graph:
357
print(triple)
358
```
359
360
### SPARQL Updates
361
362
```python
363
from rdflib import Graph, Literal, URIRef
364
from rdflib.namespace import FOAF
365
366
g = Graph()
367
368
# INSERT DATA update
369
insert_update = """
370
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
371
INSERT DATA {
372
<http://example.org/person/1> foaf:name "John Doe" ;
373
foaf:age 30 ;
374
foaf:mbox <mailto:john@example.com> .
375
}
376
"""
377
378
g.update(insert_update)
379
380
# INSERT/DELETE with WHERE clause
381
modify_update = """
382
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
383
DELETE { ?person foaf:age ?old_age }
384
INSERT { ?person foaf:age ?new_age }
385
WHERE {
386
?person foaf:name "John Doe" .
387
?person foaf:age ?old_age .
388
BIND(?old_age + 1 AS ?new_age)
389
}
390
"""
391
392
g.update(modify_update)
393
394
# DELETE WHERE update
395
delete_update = """
396
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
397
DELETE WHERE {
398
?person foaf:mbox ?email .
399
FILTER(CONTAINS(STR(?email), "spam"))
400
}
401
"""
402
403
g.update(delete_update)
404
```
405
406
### Complex Queries with SPARQL 1.1 Features
407
408
```python
409
from rdflib import Graph
410
411
g = Graph()
412
g.parse("complex_data.ttl", format="turtle")
413
414
# Query with aggregation, grouping, and subqueries
415
complex_query = """
416
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
417
PREFIX org: <http://www.w3.org/ns/org#>
418
419
SELECT ?org_name (COUNT(?person) AS ?employee_count) (AVG(?age) AS ?avg_age) WHERE {
420
?person foaf:name ?name .
421
?person foaf:age ?age .
422
?person org:memberOf ?org .
423
?org foaf:name ?org_name .
424
425
# Subquery to filter organizations with > 5 employees
426
{
427
SELECT ?org WHERE {
428
?person org:memberOf ?org .
429
}
430
GROUP BY ?org
431
HAVING(COUNT(?person) > 5)
432
}
433
}
434
GROUP BY ?org_name
435
ORDER BY DESC(?employee_count)
436
"""
437
438
results = g.query(complex_query)
439
for row in results:
440
print(f"Org: {row.org_name}, Employees: {row.employee_count}, Avg Age: {row.avg_age}")
441
```
442
443
### Result Serialization
444
445
```python
446
from rdflib import Graph
447
448
g = Graph()
449
# ... populate and query ...
450
451
results = g.query("SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 10")
452
453
# Serialize to different formats
454
xml_results = results.serialize(format='xml')
455
json_results = results.serialize(format='json')
456
csv_results = results.serialize(format='csv')
457
tsv_results = results.serialize(format='tsv')
458
459
# Save to file
460
with open('results.json', 'w') as f:
461
f.write(json_results)
462
```
463
464
### Custom SPARQL Functions
465
466
```python
467
from rdflib import Graph, Literal
468
from rdflib.plugins.sparql.evalutils import register_custom_function
469
from rdflib.namespace import XSD
470
471
def custom_upper(arg):
472
"""Custom SPARQL function to uppercase strings."""
473
if isinstance(arg, Literal):
474
return Literal(str(arg).upper())
475
return arg
476
477
# Register custom function
478
register_custom_function(
479
"http://example.org/functions#upper",
480
custom_upper,
481
return_type=XSD.string
482
)
483
484
g = Graph()
485
# ... populate graph ...
486
487
# Use custom function in query
488
query = """
489
PREFIX fn: <http://example.org/functions#>
490
SELECT ?name ?upper_name WHERE {
491
?person foaf:name ?name .
492
BIND(fn:upper(?name) AS ?upper_name)
493
}
494
"""
495
496
results = g.query(query)
497
for row in results:
498
print(f"Original: {row.name}, Upper: {row.upper_name}")
499
```