Conformance tests#

The algorithm is validated against two test suites: the W3C R2RML test suite and the RML RDB test cases from a fork of rml-io-registry. Both are included as git submodules. Forward mapping uses RMLMapper v8.1.0 and inversion uses KGI.

Defining invertibility#

Given a mapping M and the RDF graph G = M(D) produced by applying M to a relational instance D, the inversion function M⁻¹ attempts to reconstruct D from G. Two properties are distinguished:

  • Recoverability: the reconstructed instance D’ = M⁻¹(G) is consistent with the information that M preserves in G. Values, rows and tables that survive the forward mapping are reproduced correctly.

  • Completeness: D’ = D. Every row, column, duplicate and NULL present in D is reconstructed.

Test cases are therefore classified into these outcomes:

Outcome

Meaning

Fully inverted

D’ = D

Partially inverted

D’ ⊊ D with characterised loss (columns, rows, multiplicity or tables)

Non-invertible

Mapping does not preserve D in G (structural limitation)

Not supported

Engine limitation unrelated to invertibility (e.g. SQL queries as logical sources)

Error test case

The specification requires the mapping to stop, so no graph may exist to invert

Not tested

The case does not run on the selected database

Mismatch

D’ differs from D and the difference has no characterised cause

Execution error

The run stopped before it could classify the case

Running the test suite#

Use the root Makefile entry point. Docker must be running, and Java 21 or newer must be available for RMLMapper. The RMLMapper v8.1.0 jar is downloaded automatically on the first forward mapping run:

make test-conformance

DATABASE accepts postgresql and mysql. PostgreSQL is the default and runs all 121 cases:

make test-conformance DATABASE=postgresql

MySQL 9.7.1 runs 60 R2RML cases:

make test-conformance DATABASE=mysql

R2RMLTC0002f and R2RMLTC0018a run only with PostgreSQL. The 59 RML cases are skipped with MySQL because the RML Core RDB test suite does not yet provide MySQL variants.

Dashboard#

Start the dashboard and its PostgreSQL and MySQL databases with Docker Compose:

make submodules
docker compose up --build

Open http://localhost:5000, then choose the database and the test suite.

W3C R2RML test suite#

The R2RML test suite contains 62 test cases.

Outcome

PostgreSQL

MySQL

Fully inverted

21

20

Partially inverted

13

13

Non-invertible

2

2

Not supported

13

13

Error test case

12

11

Mismatch

1

1

Not tested

0

2

Partially inverted (13)#

Each case recovers the information preserved in the RDF graph, but the forward mapping discards part of the source. Sub-categories are counted per tag: a test may contribute to more than one sub-category when multiple forms of loss co-occur, so the counts below sum to more than the number of tests.

Sub-category

PostgreSQL

MySQL

Columns lost (unmapped or unassignable columns)

8

8

Rows lost (NULL in subject template)

1

1

Multiplicity lost (duplicate rows collapsed)

4

4

Tables lost (unmapped tables)

1

1

One test (R2RMLTC0012a) is tagged with two sub-categories at once: the Lives table has no triples map, and IOUs has non-unique subject identifiers that collapse duplicates.

Non-invertible (2)#

Reason

PostgreSQL

MySQL

Constant-only mapping

1

1

Sole column reference has an IRI term type (ambiguous base IRI resolution)

1

1

R2RMLTC0020a maps a single-column table through a subject map with an IRI term type over that column. The column is unassignable and no other term map names one, so nothing remains to reconstruct.

Mismatch (1)#

R2RMLTC0012b is the only case that reconstructs values differing from the source, so its inversion is neither complete nor recoverable. It builds the blank node label of the Lives table from the template {fname}{lname}, and because the two placeholders are adjacent the label BobSmith carries no boundary between them, so the reconstruction assigns the whole label to lname and leaves fname empty.

RML test suite#

The RML test suite comes from a fork of rml-io-registry and contains 59 RDB test cases.

Outcome

Count

Fully inverted

13

Partially inverted

21

Non-invertible

2

Not supported

10

Error test case

12

Mismatch

1

Partially inverted (21)#

Sub-categories are counted per tag; a test contributes to every form of loss that applies, so the counts below sum to more than the number of tests.

Sub-category

Count

Columns lost (unmapped or unassignable columns)

16

Rows lost (NULL in subject template)

1

Multiplicity lost (duplicate rows collapsed)

4

Tables lost (unmapped tables)

1

One test (RMLTC0012a) is tagged with two sub-categories at once, mirroring its R2RML counterpart: the Lives table has no triples map, and IOUs has non-unique subject identifiers that collapse duplicates.

Test cases sharing an identifier across the two suites are not always equivalent: the RML-Core suite sometimes changed the source data. The seven RMLTC0007 variants use a student table with an extra LastName column that no term map references. This is the same data as their RMLTC0007-JSON counterparts in the RML-Core suite, so they classify as partially inverted (columns lost), whereas the R2RML 0007 tests map every column and are fully inverted.

A column can also be lost through a join condition. RMLTC0021a (an RML-Core addition with no R2RML counterpart) joins the student table with itself on the Sport column, whose values never appear in the generated RDF: the graph records which students share a sport, but not which sport. A join condition equates its child and parent columns, so a join column counts as covered only when the column on the other side is emitted by a term map; here neither side is, so Sport is counted as lost.

Non-invertible (2)#

Reason

Count

Constant-only mapping

1

Sole column reference has an IRI term type (ambiguous base IRI resolution)

1

Mismatch (1)#

RMLTC0012b-RDB reproduces the defect described for its R2RML counterpart: the label built from two adjacent template placeholders cannot be split back into fname and lname.