Skip to content

Graph lifecycle ​

Four whole-graph operations (drop_graph, clear_graph, copy_graph and move_graph) that manage a named graph as one unit instead of row by row.

What it does ​

Each operation takes graph IRIs (recommended) or graph ids, and returns the number of triples it touched.

FunctionSignaturesWhat it does
delete_foreverdrop_graphdrop_graph(iri TEXT, cascade BOOLEAN DEFAULT TRUE)
drop_graph(id BIGINT, cascade BOOLEAN DEFAULT TRUE)
Removes the graph, its triples and its IRI.
layers_clearclear_graphclear_graph(iri TEXT)
clear_graph(id BIGINT)
Removes every triple; the graph, its id and its IRI stay.
content_copycopy_graphcopy_graph(src_iri TEXT, dst_iri TEXT)
copy_graph(src BIGINT, dst BIGINT)
Appends every triple of src, inferred included, into dst.
swap_horizmove_graphmove_graph(src_iri TEXT, dst_iri TEXT)
move_graph(src BIGINT, dst BIGINT)
Moves every triple into an empty dst, then drops src.

All four return BIGINT: the number of triples dropped, cleared, copied or moved.

What they have in common:

  • Transactional. They run in your transaction; a ROLLBACK undoes them.
  • IRI forms refuse unknown IRIs with 42704, which catches typos. To copy or move by IRI, create the destination with pgrdf.add_graph(iri) first.
  • Id forms are lenient. An id with no graph behind it returns 0, and copy_graph / move_graph create a missing destination named urn:pgrdf:graph:<id>.
  • Locked graphs refuse with 55P03. See Locking a graph.
  • Inferred triples are part of the graph. Clear and drop remove them; copy and move carry them along, and the destination's materialization then reads unknown until you run materialize on it.
  • Results show in the inventory. pgrdf.graph_inventory() lists every graph with its asserted and inferred counts, lock state and reasoning freshness. See the inventory.

Refusals carry a SQLSTATE: 42704 unknown graph, 55000 non-empty move destination, 2BP01 inferred triples under cascade => false, 22023 invalid argument, 55P03 locked. The full table is on Errors and diagnostics.

Why you'd use them ​

  • Project managers scoping multi-tenant or multi-snapshot work: offboarding a tenant is one drop_graph, promoting a snapshot is one move_graph. No row-by-row deletes.
  • Data scientists building incremental pipelines: stage data in a scratch graph, validate it, then move it into the production graph in the same transaction.
  • Ontologists publishing ontology versions: copy the current version, evolve the copy, materialize it, then promote it.
  • Operators doing maintenance: removing or emptying a graph is a partition-level operation, not a DELETE against the whole quad table.

Worked example — stage, reason, validate, promote ​

sql
-- Production already exists and holds last quarter's data.
SELECT pgrdf.add_graph('http://example.org/orders');
SELECT pgrdf.parse_turtle('@prefix ex: <http://example.org/> . ex:o0 a ex:Order .',
                          pgrdf.graph_id('http://example.org/orders'));

-- 1. Stage the new data in a scratch graph.
SELECT pgrdf.add_graph('http://example.org/orders/staging');
SELECT pgrdf.parse_turtle('
@prefix ex:   <http://example.org/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .

ex:RushOrder rdfs:subClassOf ex:Order .
ex:o1 a ex:Order     ; ex:total "120.00"^^xsd:decimal .
ex:o2 a ex:RushOrder ; ex:total "80.50"^^xsd:decimal .
', pgrdf.graph_id('http://example.org/orders/staging'));
-- → 5

-- 2. Reason over it: ex:o2 is also an ex:Order.
SELECT pgrdf.materialize(pgrdf.graph_id('http://example.org/orders/staging'), 'rdfs')
       ->> 'inferred_triples_written';
-- → 1

-- 3. Validate it: every order needs a total.
SELECT pgrdf.add_graph('http://example.org/orders/shapes');
SELECT pgrdf.parse_turtle('
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <http://example.org/> .

ex:OrderShape a sh:NodeShape ;
    sh:targetClass ex:Order ;
    sh:property [ sh:path ex:total ; sh:minCount 1 ] .
', pgrdf.graph_id('http://example.org/orders/shapes'));

SELECT pgrdf.validate(pgrdf.graph_id('http://example.org/orders/staging'),
                      pgrdf.graph_id('http://example.org/orders/shapes')) ->> 'conforms';
-- → true

-- 4. Promote: empty production and move staging into it, atomically.
BEGIN;
SELECT pgrdf.clear_graph('http://example.org/orders');
-- → 1
SELECT pgrdf.move_graph('http://example.org/orders/staging', 'http://example.org/orders');
-- → 6
COMMIT;

SELECT graph_id, iri, asserted, inferred, materialization FROM pgrdf.graph_inventory();
--  graph_id |               iri                | asserted | inferred | materialization
-- ----------+----------------------------------+----------+----------+-----------------
--         0 | urn:pgrdf:graph:0                |        0 |        0 | never
--         1 | http://example.org/orders        |        5 |        1 | unknown
--         3 | http://example.org/orders/shapes |        5 |        0 | never

Production now holds the staged data under its own IRI, and the staging graph is gone. materialization reads unknown because the inferred triple arrived with the move; re-run materialize on the production graph and it reads current.

If any step fails, nothing before it inside the transaction is kept.

See also ​

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