Inspect a query
Two functions look at a query without running it:
| Function | Returns |
|---|---|
pgrdf.sparql_parse(q) → jsonb | How pgRDF parsed the query: its form, variables and triple patterns, plus features it flagged as unsupported. Works for every query form, UPDATE included. |
pgrdf.sparql_sql(q) → text | The SQL pgRDF would run for a SELECT or ASK query. |
sparql_parse
SELECT jsonb_pretty(pgrdf.sparql_parse($$
SELECT ?s WHERE { ?s ?p ?o OPTIONAL { ?s <http://x/n> ?n } }
$$));{
"form": "SELECT",
"variables": ["s", "p", "o", "n"],
"bgp_patterns": [
{"o": {"var": "o"}, "p": {"var": "p"}, "s": {"var": "s"}},
{"o": {"var": "n"}, "p": {"iri": "http://x/n"}, "s": {"var": "s"}}
],
"bgp_pattern_count": 2,
"unsupported_algebra": []
}| Key | Meaning |
|---|---|
form | SELECT, ASK, CONSTRUCT, DESCRIBE or UPDATE. |
variables | Every variable in the query, not only the projected ones. |
bgp_patterns | The triple patterns; each position is a var or an iri. |
bgp_pattern_count | How many triple patterns. |
unsupported_algebra | Features pgRDF found that it can't run. |
A query that doesn't parse raises an error that gives the line and column: sparql_parse: error at 1:25: expected one of ….
What unsupported_algebra catches
SELECT pgrdf.sparql_parse(
'SELECT * WHERE { SERVICE <http://x> { ?s ?p ?o } }') -> 'unsupported_algebra';
-- ["Service (federation)"]
SELECT pgrdf.sparql_parse($$
PREFIX ex: <http://example.org/>
SELECT ?x WHERE { ?x (ex:a/ex:b)+ ?o }
$$) -> 'unsupported_algebra';
-- ["Path (recursive/alternation property path)"]An empty list is not a guarantee
unsupported_algebra flags SERVICE and the property paths pgRDF can't run (negated sets and nested paths). Other refusals are found only when the query runs, and are not listed here: FILTER EXISTS, LANGMATCHES, COALESCE and other functions, blank nodes in patterns, sequence paths, UNION inside OPTIONAL, and VALUES on a GRAPH variable. See Not supported.
UPDATE
For an update, sparql_parse shows what each operation will do and which graphs it targets:
SELECT jsonb_pretty(pgrdf.sparql_parse($$
WITH <http://example.org/g1>
DELETE { ?s <http://e.com/p> ?o }
INSERT { ?s <http://e.com/q> ?o }
WHERE { ?s <http://e.com/p> ?o }
$$));{
"form": "UPDATE",
"operations": [
{
"op": "DeleteInsert",
"kind": "DELETE_INSERT_WHERE",
"with_graph": "http://example.org/g1",
"template_graphs": ["http://example.org/g1"],
"where_pattern_size": 1,
"delete_template_size": 1,
"insert_template_size": 1
}
],
"unsupported_algebra": []
}op | Fields |
|---|---|
InsertData, DeleteData | triples, graphs |
DeleteInsert | kind (INSERT_WHERE, DELETE_WHERE or DELETE_INSERT_WHERE), template_graphs, with_graph when WITH is used, and the where_pattern_size, delete_template_size and insert_template_size counts |
Create, Clear, Drop | target (DEFAULT, ALL or NAMED <iri>), silent |
In graphs and template_graphs, "DEFAULT" is the default graph and "?g" is a graph chosen by a variable:
SELECT pgrdf.sparql_parse($$
PREFIX ex: <http://example.org/>
INSERT DATA { ex:a ex:b ex:c . GRAPH <http://example.org/g2> { ex:a ex:b ex:d } }
$$) -> 'operations';
-- [{"op": "InsertData", "graphs": ["DEFAULT", "http://example.org/g2"], "triples": 2}]
SELECT pgrdf.sparql_parse('DROP SILENT GRAPH <http://example.org/stale>') -> 'operations';
-- [{"op": "Drop", "silent": true, "target": "NAMED <http://example.org/stale>"}]
SELECT pgrdf.sparql_parse('CLEAR DEFAULT') -> 'operations';
-- [{"op": "Clear", "silent": false, "target": "DEFAULT"}]CONSTRUCT and DESCRIBE
SELECT pgrdf.sparql_parse($$
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
CONSTRUCT { ?s foaf:nick ?n } WHERE { ?s foaf:name ?n }
$$) -> 'template';
-- {"variables": ["?n", "?s"], "triple_count": 1, "has_variables": true,
-- "has_blank_nodes": false, "has_constants_only": false}
SELECT pgrdf.sparql_parse('DESCRIBE <http://example.org/bob>') -> 'describe';
-- {"kind": "constant", "has_where": false,
-- "constant_iris": ["http://example.org/bob"], "variable_terms": []}A CONSTRUCT report also has shorthand (true for CONSTRUCT WHERE) and where_shape, which lists the pattern's variables, triple count and the named graphs it uses.
sparql_sql
pgrdf.sparql_sql(q) returns the SQL that pgrdf.sparql(q) would run. With the sample data loaded:
SELECT pgrdf.sparql_sql($$
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?n WHERE { ?p a foaf:Person ; foaf:name ?n }
$$);
-- SELECT (SELECT lexical_value FROM pgrdf._pgrdf_dictionary
-- WHERE id = q2.object_id) AS "n" FROM pgrdf._pgrdf_quads q1
-- INNER JOIN pgrdf._pgrdf_quads q2 ON (q2.subject_id = q1.subject_id AND q2.predicate_id = 15)
-- WHERE q1.predicate_id = 12 AND q1.object_id = 19The numbers are the ids of the IRIs in your database, so they differ from one database to another. The tables named are pgRDF's internal storage: read the SQL, but don't build on those names.
- It covers
SELECTandASK.CONSTRUCTand UPDATE requests are refused. - A query pgRDF can't run is refused here with the same error
pgrdf.sparql()would raise (for example0A000forSERVICE).
EXPLAIN a query
Pair sparql_sql with PostgreSQL's EXPLAIN to see how a slow query is planned. In psql, store the SQL in a variable with \gset, then explain it:
SELECT pgrdf.sparql_sql($$
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name WHERE { ?p a foaf:Person ; foaf:name ?name }
$$) AS q \gset
EXPLAIN (COSTS OFF) :q;EXPLAIN (ANALYZE) :q; runs the query as well and shows timings. In other clients, fetch the text and send EXPLAIN followed by it.
The property paths page uses this to check that a path takes the faster route after materialize.