copy_graph — copy one graph into another
Append every triple of one graph into another, inferred triples included. Returns the number of triples copied.
What it does
pgrdf.copy_graph(src_iri TEXT, dst_iri TEXT) → BIGINT
pgrdf.copy_graph(src BIGINT, dst BIGINT) → BIGINT- By IRI, both graphs must exist. Create the destination with
pgrdf.add_graph(iri)first; an unknown source or destination IRI refuses with42704. - By id, a missing destination is created and named
urn:pgrdf:graph:<id>. Copying from an id that has no graph returns0and creates nothing. - Copy appends. Triples already in the destination stay. Copying twice puts every triple in twice. For an exact copy, clear the destination first (see below).
- Inferred triples come along. The copy's
materializationreadsunknowningraph_inventory(), because nomaterializerun produced them for that graph. Runmaterializeon the copy if you rely on them. - The source is untouched, and may itself be locked. A locked destination refuses (
55P03). - It is transactional, and its time grows with the number of triples copied.
Why you'd use it
- Project managers — fork a baseline graph for a parallel experiment and keep the original untouched.
- Data scientists — take a scratch copy of a production graph to experiment on.
- Ontologists — start a new vocabulary version from a copy of the current one, then evolve the copy.
- Backend engineers — copy production into staging, change staging, then
move_graphit back.
Example
sql
SELECT pgrdf.add_graph('http://example.org/orders');
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'));
-- → 5
SELECT pgrdf.materialize(pgrdf.graph_id('http://example.org/orders'), 'rdfs')
->> 'inferred_triples_written';
-- → 1 (ex:o2 a ex:Order)
-- Copying by IRI needs the destination to exist.
SELECT pgrdf.add_graph('http://example.org/orders-fork');
SELECT pgrdf.copy_graph('http://example.org/orders', 'http://example.org/orders-fork');
-- → 6 (5 asserted + 1 inferred)
SELECT iri, asserted, inferred, materialization
FROM pgrdf.graph_inventory()
WHERE iri LIKE 'http://example.org/orders%';
-- iri | asserted | inferred | materialization
-- --------------------------------+----------+----------+-----------------
-- http://example.org/orders | 5 | 1 | current
-- http://example.org/orders-fork | 5 | 1 | unknown
SELECT pgrdf.graph_digest(pgrdf.graph_id('http://example.org/orders')) =
pgrdf.graph_digest(pgrdf.graph_id('http://example.org/orders-fork')) AS identical;
-- → tgraph_digest compares the asserted triples, so it confirms the copy is the same graph.
Copy appends
Running the same copy again doubles the destination:
sql
SELECT pgrdf.copy_graph('http://example.org/orders', 'http://example.org/orders-fork');
-- → 6
SELECT asserted, inferred FROM pgrdf.graph_inventory()
WHERE iri = 'http://example.org/orders-fork';
-- asserted | inferred
-- ----------+----------
-- 10 | 2For an exact copy, clear the destination first, then re-run reasoning on the result:
sql
BEGIN;
SELECT pgrdf.clear_graph('http://example.org/orders-fork');
SELECT pgrdf.copy_graph('http://example.org/orders', 'http://example.org/orders-fork');
COMMIT;
SELECT pgrdf.materialize(pgrdf.graph_id('http://example.org/orders-fork'), 'rdfs');
-- the fork's materialization now reads currentRefusals
| SQLSTATE | When | Example message |
|---|---|---|
42704 | The source or destination IRI is not a known graph | copy_graph: unknown iri "http://example.org/orders-copy" |
22023 | Source and destination are the same graph, or an id is negative | copy_graph: src and dst must differ (both = 1) |
55P03 | The destination is locked | pgrdf: graph 1 is locked (release review): copy_graph (destination) refused. Unlock with pgrdf.unlock_graph(1, '<reason>'). |
The full table is on Errors and diagnostics.
See also
- Graph lifecycle — the four operations side by side.
move_graph— copy into an empty graph and drop the source.- Carving out a subgraph — copy only part of a graph.