RDF-star

RDF-star (RDF*) extends RDF by allowing triples to be used as subjects or objects in other triples. This enables statements about statements — useful for provenance, temporal annotations, and LPG-style edge properties.

Overview

In RDF-star a quoted triple << s p o >> can appear in subject or object position:

<< <ex:alice> <ex:knows> <ex:bob> >> <ex:assertedBy> <ex:carol> .

pg_ripple stores quoted triples in the dictionary with kind = 5 (KIND_QUOTED_TRIPLE) and encodes them using their component dictionary IDs.

encode_triple

pg_ripple.encode_triple(
    subject   TEXT,
    predicate TEXT,
    object    TEXT
) RETURNS BIGINT

Encodes a triple as a dictionary entry and returns its BIGINT ID. Idempotent — repeated calls with the same triple return the same ID.

SELECT pg_ripple.encode_triple(
    '<https://example.org/alice>',
    '<https://example.org/knows>',
    '<https://example.org/bob>'
);

decode_triple

pg_ripple.decode_triple(id BIGINT) RETURNS JSONB

Returns the triple encoded at a given dictionary ID as a JSONB object {"s":…,"p":…,"o":…}.

SELECT pg_ripple.decode_triple(42);
-- Returns: {"s":"<https://example.org/alice>","p":"<https://example.org/knows>","o":"<https://example.org/bob>"}

insert_triple and SIDs

insert_triple() returns a statement identifier (SID) — a globally-unique BIGINT for the inserted triple. SIDs can be used as subjects or objects in subsequent triples to annotate the statement.

DECLARE sid BIGINT;
SELECT pg_ripple.insert_triple(
    '<https://example.org/alice>',
    '<https://example.org/knows>',
    '<https://example.org/bob>'
) INTO sid;

-- Annotate the statement with provenance
SELECT pg_ripple.insert_triple(
    '<https://example.org/sid-' || sid || '>',
    '<https://example.org/assertedBy>',
    '<https://example.org/carol>'
);

get_statement

pg_ripple.get_statement(i BIGINT) RETURNS JSONB

Looks up a triple by its SID and returns it as {"s":…,"p":…,"o":…,"g":…}.

SELECT pg_ripple.get_statement(1);
-- Returns: {"s":"<ex:alice>","p":"<ex:knows>","o":"<ex:bob>","g":"0"}

Loading RDF-star data

load_ntriples() accepts N-Triples-star input with subject-position and object-position quoted triples:

SELECT pg_ripple.load_ntriples('
<< <https://example.org/alice> <https://example.org/knows> <https://example.org/bob> >>
    <https://example.org/assertedBy>
    <https://example.org/carol> .
');

SPARQL-star patterns

Ground (all-constant) quoted triple patterns are supported in SPARQL WHERE clauses:

SELECT * FROM pg_ripple.sparql('
  SELECT ?who WHERE {
    << <https://example.org/alice> <https://example.org/knows> <https://example.org/bob> >>
        <https://example.org/assertedBy> ?who
  }
');

LPG edge property mapping

RDF-star is a natural fit for encoding LPG edge properties: a quoted triple represents the edge, and subsequent triples about the quoted triple encode the properties.

<< <ex:alice> <ex:knows> <ex:bob> >> <ex:since>   "2023-01-01"^^xsd:date .
<< <ex:alice> <ex:knows> <ex:bob> >> <ex:strength> "strong" .

Variable-inside-quoted-triple patterns (v0.48.0)

As of v0.48.0, variables inside quoted triple patterns are supported. This allows binding variables to the components of a quoted triple that appears as the subject or object of another triple:

-- Bind ?v to the object component of the matching quoted triple
SELECT * FROM pg_ripple.sparql('
  PREFIX ex: <http://example.org/>
  SELECT ?v ?who WHERE {
    << ex:alice ex:age ?v >> ex:assertedBy ?who .
  }
');

-- Bind all three components
SELECT * FROM pg_ripple.sparql('
  PREFIX ex: <http://example.org/>
  SELECT ?s ?p ?o ?who WHERE {
    << ?s ?p ?o >> ex:assertedBy ?who .
  }
');

This works by joining the _pg_ripple.dictionary table on the qt_s, qt_p, and qt_o columns (available for entries with kind = 5).