SPARQL Compliance Matrix

pg_ripple implements the full SPARQL 1.1 specification suite. This page details conformance status for every feature in the W3C SPARQL 1.1 Query, Update, and Protocol recommendations.

Full compliance

As of v0.46.0, pg_ripple passes 100% of the W3C SPARQL 1.1 test suite (~3 000 tests), ≥ 99.9% of the Apache Jena edge-case suite (~1 000 tests), all 100 WatDiv query templates at 10 M-triple scale with correctness validated to ±0.1% row-count baselines, all 14 LUBM queries with OWL RL inference correctness, and ≥ 80% of the W3C OWL 2 RL conformance suite.


SPARQL 1.1 Query — Query Forms

FeatureStatusSinceNotes
SELECT✅ Supportedv0.1.0Full projection with expressions
CONSTRUCT✅ Supportedv0.8.0Returns triples as JSON, Turtle, or JSON-LD
ASK✅ Supportedv0.8.0Returns boolean
DESCRIBE✅ Supportedv0.8.0Symmetric concise bounded description

SPARQL 1.1 Query — Algebra Operations

FeatureStatusSinceNotes
Basic Graph Pattern (BGP)✅ Supportedv0.1.0Translated to VP table joins
Join (inner)✅ Supportedv0.1.0
LeftJoin (OPTIONAL)✅ Supportedv0.1.0Downgraded to INNER JOIN when SHACL sh:minCount 1 is set
Filter✅ Supportedv0.1.0All comparison, logical, and arithmetic operators
Union✅ Supportedv0.5.0UNION ALL in generated SQL
Minus✅ Supportedv0.5.0EXCEPT in generated SQL
Extend (BIND)✅ Supportedv0.1.0
Group (GROUP BY)✅ Supportedv0.5.0
Having✅ Supportedv0.5.0
OrderBy✅ Supportedv0.1.0
Project✅ Supportedv0.1.0
Distinct✅ Supportedv0.1.0Omitted when SHACL sh:maxCount 1 is set
Reduced✅ Supportedv0.5.0Treated as hint; may or may not deduplicate
Slice (LIMIT/OFFSET)✅ Supportedv0.1.0
Service (SERVICE)✅ Supportedv0.16.0Federated query via HTTP
Service Silent (SERVICE SILENT)✅ Supportedv0.16.0Returns empty on endpoint failure
Values (VALUES)✅ Supportedv0.5.0Inline data bindings
Lateral (LATERAL)✅ Supportedv0.22.0PostgreSQL LATERAL JOIN
Subqueries✅ Supportedv0.5.0Nested SELECT
Negation (NOT EXISTS)✅ Supportedv0.5.0
Negation (EXISTS)✅ Supportedv0.5.0

SPARQL 1.1 Query — Property Paths

FeatureStatusSinceNotes
Sequence path (/)✅ Supportedv0.5.0
Alternative path (|)✅ Supportedv0.5.0
Inverse path (^)✅ Supportedv0.5.0
Zero-or-more (*)✅ Supportedv0.5.0WITH RECURSIVE … CYCLE
One-or-more (+)✅ Supportedv0.5.0WITH RECURSIVE … CYCLE
Zero-or-one (?)✅ Supportedv0.5.0
Negated property set (!(p1|p2))✅ Supportedv0.5.0
Fixed-length path ({n})✅ Supportedv0.5.0Unrolled to n joins
Variable-length path ({n,m})✅ Supportedv0.5.0Bounded recursion

Cycle detection

All recursive property paths use PostgreSQL 18's native CYCLE clause for hash-based cycle detection, bounded by pg_ripple.max_path_depth (default: 10).


SPARQL 1.1 Query — Aggregates

FeatureStatusSinceNotes
COUNT✅ Supportedv0.5.0Including COUNT(DISTINCT *)
SUM✅ Supportedv0.5.0
AVG✅ Supportedv0.5.0
MIN✅ Supportedv0.5.0
MAX✅ Supportedv0.5.0
GROUP_CONCAT✅ Supportedv0.5.0With custom separator
SAMPLE✅ Supportedv0.5.0

SPARQL 1.1 Query — Built-in Functions

FunctionStatusSince
STR()✅ Supportedv0.1.0
LANG()✅ Supportedv0.3.0
DATATYPE()✅ Supportedv0.3.0
IRI() / URI()✅ Supportedv0.5.0
BNODE()✅ Supportedv0.5.0
RAND()✅ Supportedv0.5.0
ABS()✅ Supportedv0.1.0
CEIL()✅ Supportedv0.1.0
FLOOR()✅ Supportedv0.1.0
ROUND()✅ Supportedv0.1.0
CONCAT()✅ Supportedv0.5.0
STRLEN()✅ Supportedv0.1.0
UCASE()✅ Supportedv0.1.0
LCASE()✅ Supportedv0.1.0
ENCODE_FOR_URI()✅ Supportedv0.5.0
CONTAINS()✅ Supportedv0.1.0
STRSTARTS()✅ Supportedv0.1.0
STRENDS()✅ Supportedv0.1.0
STRBEFORE()✅ Supportedv0.5.0
STRAFTER()✅ Supportedv0.5.0
YEAR()✅ Supportedv0.5.0
MONTH()✅ Supportedv0.5.0
DAY()✅ Supportedv0.5.0
HOURS()✅ Supportedv0.5.0
MINUTES()✅ Supportedv0.5.0
SECONDS()✅ Supportedv0.5.0
TIMEZONE()✅ Supportedv0.5.0
TZ()✅ Supportedv0.5.0
NOW()✅ Supportedv0.5.0
UUID()✅ Supportedv0.5.0
STRUUID()✅ Supportedv0.5.0
MD5()✅ Supportedv0.5.0
SHA1()✅ Supportedv0.5.0
SHA256()✅ Supportedv0.5.0
SHA384()✅ Supportedv0.5.0
SHA512()✅ Supportedv0.5.0
COALESCE()✅ Supportedv0.1.0
IF()✅ Supportedv0.1.0
STRLANG()✅ Supportedv0.5.0
STRDT()✅ Supportedv0.5.0
isIRI() / isURI()✅ Supportedv0.1.0
isBlank()✅ Supportedv0.1.0
isLiteral()✅ Supportedv0.1.0
isNumeric()✅ Supportedv0.5.0
REGEX()✅ Supportedv0.1.0
REPLACE()✅ Supportedv0.5.0
SUBSTR()✅ Supportedv0.5.0
BOUND()✅ Supportedv0.1.0
IN / NOT IN✅ Supportedv0.5.0
TRIPLE() (RDF-star)✅ Supportedv0.4.0
SUBJECT() (RDF-star)✅ Supportedv0.4.0
PREDICATE() (RDF-star)✅ Supportedv0.4.0
OBJECT() (RDF-star)✅ Supportedv0.4.0
isTRIPLE() (RDF-star)✅ Supportedv0.4.0

SPARQL 1.1 Query — Typed Literals

DatatypeStatusNotes
xsd:integer✅ SupportedMaps to PostgreSQL BIGINT
xsd:decimal✅ SupportedMaps to NUMERIC
xsd:float✅ SupportedMaps to REAL
xsd:double✅ SupportedMaps to DOUBLE PRECISION
xsd:boolean✅ SupportedMaps to BOOLEAN
xsd:string✅ SupportedDefault literal type
xsd:dateTime✅ SupportedMaps to TIMESTAMPTZ
xsd:date✅ SupportedMaps to DATE
xsd:time✅ SupportedMaps to TIME
xsd:gYear✅ SupportedStored as string, compared lexically
Language-tagged strings✅ Supported"text"@en syntax

SPARQL 1.1 Update

OperationStatusSinceNotes
INSERT DATA✅ Supportedv0.7.0
DELETE DATA✅ Supportedv0.7.0
DELETE WHERE✅ Supportedv0.7.0
DELETE/INSERT WHERE✅ Supportedv0.7.0
INSERT WHERE✅ Supportedv0.7.0
LOAD✅ Supportedv0.7.0Via pg_ripple_http or direct file
CLEAR GRAPH✅ Supportedv0.7.0
CLEAR DEFAULT✅ Supportedv0.7.0
CLEAR NAMED✅ Supportedv0.7.0
CLEAR ALL✅ Supportedv0.7.0
DROP GRAPH✅ Supportedv0.7.0
DROP DEFAULT✅ Supportedv0.7.0
DROP NAMED✅ Supportedv0.7.0
DROP ALL✅ Supportedv0.7.0
CREATE GRAPH✅ Supportedv0.7.0
CREATE SILENT GRAPH✅ Supportedv0.7.0
COPY✅ Supportedv0.21.0
MOVE✅ Supportedv0.21.0
ADD✅ Supportedv0.21.0
Multi-statement (; separator)✅ Supportedv0.7.0
USING / USING NAMED✅ Supportedv0.7.0Dataset clause for updates

SPARQL 1.1 Protocol

FeatureStatusNotes
Query via HTTP GET✅ SupportedVia pg_ripple_http
Query via HTTP POST (form-encoded)✅ SupportedVia pg_ripple_http
Query via HTTP POST (direct body)✅ SupportedVia pg_ripple_http
Update via HTTP POST✅ SupportedVia pg_ripple_http
Content negotiation (Accept header)✅ SupportedJSON, Turtle, N-Triples, XML
default-graph-uri parameter✅ Supported
named-graph-uri parameter✅ Supported
Multiple default-graph-uri✅ Supported
Multiple named-graph-uri✅ Supported

Protocol endpoint

SPARQL Protocol support requires the pg_ripple_http companion service. See APIs and Integration for setup instructions.


SPARQL 1.1 Service Description

FeatureStatusNotes
Service description at endpoint root✅ SupportedVia pg_ripple_http
sd:supportedLanguage✅ SupportedReports SPARQL 1.1 Query and Update
sd:resultFormat✅ SupportedJSON, XML, CSV, TSV
sd:defaultDataset✅ Supported
sd:feature✅ SupportedReports sd:UnionDefaultGraph, sd:RequiresDataset

SPARQL 1.1 Graph Store HTTP Protocol

OperationStatusNotes
GET (retrieve graph)✅ SupportedVia pg_ripple_http
PUT (replace graph)✅ SupportedVia pg_ripple_http
POST (merge into graph)✅ SupportedVia pg_ripple_http
DELETE (drop graph)✅ SupportedVia pg_ripple_http
?default parameter✅ Supported
?graph=<uri> parameter✅ Supported

RDF-star / SPARQL-star

FeatureStatusSinceNotes
Quoted triple storage✅ Supportedv0.4.0qt_s, qt_p, qt_o dictionary columns
Quoted triple in BGP✅ Supportedv0.4.0Ground patterns only
TRIPLE() constructor✅ Supportedv0.4.0
SUBJECT(), PREDICATE(), OBJECT()✅ Supportedv0.4.0
isTRIPLE()✅ Supportedv0.4.0
Annotation syntax (`{}`)✅ Supported

Extensions Beyond W3C

pg_ripple extends the SPARQL standard with additional capabilities:

FeatureNotes
pg:similar() custom functionVector similarity within SPARQL FILTER
pg:fts() custom functionFull-text search within SPARQL FILTER
pg:embed() custom functionInline embedding generation
Datalog-materialized predicatesInferred triples queryable via standard SPARQL
SHACL-optimized query plansCardinality hints from SHACL shapes
Plan cacheCompiled SQL plans cached across queries

Known Limitations

FeatureStatusNotes
langMatches()⚠️ PartialReturns 0 rows; full BCP 47 matching planned
Custom aggregate extensions❌ Not supportedStandard aggregates fully supported
Variable-in-quoted-triple << ?s ?p ?o >>⚠️ PartialReturns 0 rows with WARNING; ground patterns work
LOAD <url> from arbitrary HTTP⚠️ DependsRequires pg_ripple_http or server-side file
DESCRIBE strategy customization✅ SupportedFour strategies via GUC (v0.55.0)
Multiple result formats for SELECT⚠️ PartialJSON primary; XML/CSV/TSV via pg_ripple_http only

DESCRIBE Strategy Reference (SC13-04, v0.86.0 — supersedes v0.55.0)

pg_ripple supports three DESCRIBE algorithms selectable via the pg_ripple.describe_form GUC (default: cbd), introduced in v0.86.0. The older pg_ripple.describe_strategy GUC is deprecated (see deprecated-gucs.md) and will be removed in v1.0.0.

cbd — Concise Bounded Description (default)

Returns all triples where the described resource appears as subject, plus all triples reachable by following blank-node objects recursively. This is the minimal W3C-defined DESCRIBE semantics.

SET pg_ripple.describe_form = 'cbd';
SELECT * FROM pg_ripple.sparql('DESCRIBE <https://example.org/Alice>');

scbd — Symmetric Concise Bounded Description

Extends CBD by also including all triples where the described resource appears as object. This captures both outgoing and incoming edges. Suitable when you need the full neighbourhood of a resource.

SET pg_ripple.describe_form = 'scbd';
SELECT * FROM pg_ripple.sparql('DESCRIBE <https://example.org/Alice>');

symmetric — Permanent Alias for scbd (CB-10, v0.92.0)

symmetric is a permanent alias for scbd for readability:

SET pg_ripple.describe_form = 'symmetric';
SELECT * FROM pg_ripple.sparql('DESCRIBE <https://example.org/Alice>');

Alias contract: The alias symmetric = scbd is guaranteed stable for the pg_ripple 1.x API line. It will not be removed without a deprecation cycle and will only diverge from scbd semantics if the W3C SCBD and "symmetric extension" definitions separate in a future RDF standard. This guarantee was formally documented in v0.92.0.

Choosing a Form

FormOutgoing edgesIncoming edgesBlank-node closureSpeed
cbdMedium
scbd / symmetricSlower

The GUC can be set at the session or transaction level:

-- Session-level
SET pg_ripple.describe_form = 'scbd';

-- Transaction-level
BEGIN;
SET LOCAL pg_ripple.describe_form = 'cbd';
SELECT * FROM pg_ripple.sparql('DESCRIBE <https://example.org/Bob>');
COMMIT;

Migration note: Replace SET pg_ripple.describe_strategy = 'simple' with SET pg_ripple.describe_form = 'cbd' (the simple strategy is now the CBD default). The strategy scbd maps directly to describe_form = 'scbd'.


Blank-Node Limitations in RDF-star Quoted Triples (C13-03, v0.85.0)

Blank nodes inside RDF-star quoted triples (e.g., << _:b1 :p :o >>) do not have a canonical round-trip form in pg_ripple. When an anonymous blank node appears as the subject or object of a quoted triple, encoding and then decoding the same triple may produce a different blank-node label.

Workaround: Use named IRIs or well-known blank-node identifiers (e.g., _:b1 with a stable label) as subjects/objects of quoted triples. Alternatively, avoid blank nodes entirely in the subject/object positions of << >> patterns.

Impact: This limitation only affects blank-node-in-quoted-triple patterns. Regular blank nodes in non-quoted triples round-trip correctly.


GRAPH ?g Default-Graph Exclusion (C13-06, v0.85.0)

Per SPARQL 1.1 specification §8.3, when GRAPH ?g { ... } is used, the variable ?g is bound only to **named variable ?g is bound only to **named variable ?g is bound only to **named variable This is conformavariable ?gis bound only to **named variable?gis bound only to wivariable?gis bound only to **named variable?gis bound only to **na ?pvariable?gis bound only to **named variable?gis bound only to **naatvariable?gis bound only to **named variable?g` is bound only to **named ns triples.

To query the default graph specifically, use: WHERE nd```````````````````````````````````````````````````````````````````````valu````````````````````````````````````````````````````````````````````````````cis``````````````````````````````````````````````````````````````truncate```````````````````````````````````````````````````seconds) when serializing xsd:dateTime literals back to N-Triples format.

Example:

# Input:  "2024-01-01T12:00:00.123456789Z"^^xsd:dateTime
# Stored: 2024-01-01 12:00:00.123457+00  (rounded to microseconds by PG)
# Output: "2024-01-01T12:00:00.123"^^xsd:dateTime  (truncated to 3 decimal places)

Sub-millisecond precision is silently dropped in the output. If you require sub-millisecond precision, store the value as a plain string literal and perform comparisons manually.


RDF 1.2 / SPARQL-star Compliance Matrix (STD-02, v0.91.0)

pg_ripple supports RDF-star via the oxrdf 0.3 data model and the qt_s/qt_p/qt_o dictionary columns introduced in v0.4.0. The table below maps each RDF 1.2 / SPARQL-star feature to its implementation status.

FeatureStatusSinceNotes
<< s p o >> in subject position (BGP)✅ Implementedv0.4.0Stored via qt_s/qt_p/qt_o dictionary columns
<< s p o >> in BIND✅ Implementedv0.16.0Full expression support
<< s p o >> in FILTER✅ Implementedv0.16.0Comparison and isTriple()
<< s p o >> in CONSTRUCT✅ Implementedv0.16.0Emitted as Turtle-star
<< s p o >> in SELECT projections✅ Implementedv0.16.0
Annotation syntax `{p o}`⚠ Partial
TRIPLE(s, p, o) constructor function❌ Not implementedDepends on spargebra SPARQL 1.2 grammar update
SUBJECT() / PREDICATE() / OBJECT() destructuring❌ Not implementedDictionary join required; planned post-spargebra-1.2
REIF keyword (RDF 1.2 reification syntax)❌ Not startedspargebra grammar update required
isTriple() function✅ Implementedv0.16.0Returns true for quoted-triple subjects

Overall: pg_ripple's RDF-star foundation (v0.4.0) covers the most widely-used SPARQL-star patterns. Remaining gaps depend on spargebra 0.x adopting the SPARQL 1.2 grammar and are tracked as post-v1.0.0 work (see SPARQL 1.2 tracking).


<< >> Position Support Matrix (L15-08, v0.97.0)

This table summarises which positions a quoted triple pattern << s p o >> can appear in across all SPARQL 1.1 query and update forms. Use this matrix when writing queries that combine RDF-star with other features.

<< s p o >> positionStatusSinceNotes
Subject position in BGP✅ Supportedv0.4.0Stored via qt_s/qt_p/qt_o dictionary columns
Object position in BGP✅ Supportedv0.4.0
Subject of quoted triple in BIND✅ Supportedv0.16.0Full expression support
Nested quoted triples << << s p o >> p2 o2 >>✅ Supportedv0.4.0Dictionary recursion
In FILTER expressions✅ Supportedv0.16.0isTriple(), comparison operators
In CONSTRUCT head✅ Supportedv0.16.0Emitted as Turtle-star
In SELECT projections✅ Supportedv0.16.0
In INSERT DATA✅ Supportedv0.16.0Written to qt_s/qt_p/qt_o columns
In DELETE DATA✅ Supportedv0.16.0Matched and deleted via dictionary lookup
Variable-in-quoted-triple << ?s ?p ?o >>⚠️ Partialv0.16.0Returns 0 rows with WARNING; ground patterns work
Blank nodes inside << >>⚠️ Partialv0.4.0No document-scope isolation; avoid in multi-load scenarios
In VALUES clause✅ Supportedv0.25.0Ground quoted triples only
In GRAPH clause✅ Supportedv0.4.0Named graph + quoted triple combination
In UNION branches✅ Supportedv0.16.0
In OPTIONAL✅ Supportedv0.16.0
In property paths❌ Not supportedPath expressions inside << >> are not yet handled
In SERVICE (federation)✅ Supportedv0.4.0Forwarded as-is to remote endpoint
In GROUP BY / HAVING✅ Supportedv0.16.0
In ORDER BY✅ Supportedv0.16.0Lexicographic order on serialised form