Skip to content

Inspect a query ​

Two functions look at a query without running it:

FunctionReturns
pgrdf.sparql_parse(q) → jsonbHow 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) → textThe SQL pgRDF would run for a SELECT or ASK query.

sparql_parse ​

sql
SELECT jsonb_pretty(pgrdf.sparql_parse($$
  SELECT ?s WHERE { ?s ?p ?o OPTIONAL { ?s <http://x/n> ?n } }
$$));
json
{
    "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": []
}
KeyMeaning
formSELECT, ASK, CONSTRUCT, DESCRIBE or UPDATE.
variablesEvery variable in the query, not only the projected ones.
bgp_patternsThe triple patterns; each position is a var or an iri.
bgp_pattern_countHow many triple patterns.
unsupported_algebraFeatures 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 ​

sql
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:

sql
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 }
$$));
json
{
    "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": []
}
opFields
InsertData, DeleteDatatriples, graphs
DeleteInsertkind (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, Droptarget (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:

sql
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 ​

sql
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:

sql
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 = 19

The 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 SELECT and ASK. CONSTRUCT and UPDATE requests are refused.
  • A query pgRDF can't run is refused here with the same error pgrdf.sparql() would raise (for example 0A000 for SERVICE).

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:

sql
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.

See also ​

pgRDF is released under the MIT license. Documentation built with VitePress, served via GitHub Pages.