#001: Upgrade Oxigraph from 0.4.x to 0.5.x #1

Closed
opened 2026-04-05 12:58:38 +00:00 by daniel · 1 comment
Owner

Summary

Upgrade the Oxigraph dependency from 0.4.x to 0.5.x to gain RDF 1.2 support, performance improvements, and continued maintenance.

Blocked by

None.

Blocks

Motivation

  • Oxigraph 0.4.x only receives critical fixes; 0.5.x is the actively maintained line.
  • RDF 1.2 support (rdf:reifies, quoted triples) is needed for the entity editor's stated/non-stated pattern.
  • Faster updates and bulk loading.
  • Reduced storage footprint.

Scope of changes

Dependency bump

# Cargo.toml
oxigraph = { version = "0.5", features = ["rdf-12"] }

API migration

Every Store.query() and Store.update() call must be rewritten.

Old API (0.4.x):

let results = store.query("SELECT * WHERE { ?s ?p ?o }")?;
store.update("INSERT DATA { ... }")?;

New API (0.5.x):

let evaluator = store.query_evaluator();
let results = evaluator.prepare("SELECT * WHERE { ?s ?p ?o }")?.exec()?;

let transaction = store.start_transaction()?;
transaction.update("INSERT DATA { ... }")?;
transaction.commit()?;

Affected files

All files that call store.query() or store.update():

  • src/auth.rs — all SPARQL queries for users, teams, permissions
  • src/store.rs — dataset metadata queries and updates
  • src/migration.rs — schema version queries and updates
  • src/routes/web.rs — SPARQL updates for team/user/dataset creation
  • src/routes/files.rs — file catalog queries and updates
  • src/routes/sparql.rs — SPARQL endpoint handlers
  • src/grobid.rs — metadata update after extraction
  • src/bin/*.rs — CLI tools

Model type changes

  • Subject enum merged into NamedOrBlankNode
  • EvaluationError split into QueryEvaluationError and UpdateEvaluationError
  • QueryResults now carries a lifetime parameter

Database migration

Oxigraph 0.5.x automatically migrates 0.4.x databases on first open. This is a one-way migration — databases cannot be reopened with 0.4.x.

Procedure:

  1. Backup data directory
  2. Build with Oxigraph 0.5.x
  3. Start the application (triggers automatic migration)

Build requirements

  • Rust 1.87+
  • C++20 compiler (GCC 14 on Debian 13)

Both are available on the deployment server (degu03).

Tests

Unit tests

#[test]
fn test_store_query_new_api() {
    // Verify the new SparqlEvaluator API returns results
    let store = Store::new().unwrap();
    store.start_transaction().unwrap()
        .update("INSERT DATA { <urn:s> <urn:p> <urn:o> }")
        .unwrap().commit().unwrap();
    let results = store.query_evaluator()
        .prepare("SELECT * WHERE { ?s ?p ?o }").unwrap()
        .exec().unwrap();
    // Assert one result
}

#[test]
fn test_store_update_transaction() {
    // Verify transaction commit persists, rollback discards
    let store = Store::new().unwrap();
    let tx = store.start_transaction().unwrap();
    tx.update("INSERT DATA { <urn:s> <urn:p> <urn:o> }").unwrap();
    tx.commit().unwrap();
    // Assert triple exists

    let tx2 = store.start_transaction().unwrap();
    tx2.update("INSERT DATA { <urn:a> <urn:b> <urn:c> }").unwrap();
    drop(tx2); // rollback
    // Assert <urn:a> triple does NOT exist
}

#[test]
fn test_rdf12_quoted_triples() {
    // Verify RDF 1.2 triple terms work with rdf-12 feature
    let store = Store::new().unwrap();
    store.start_transaction().unwrap()
        .update(r#"
            PREFIX concon: <https://concon.2mia.org/ontology#>
            INSERT DATA {
                <urn:s> <urn:p> <urn:o> .
                <<( <urn:s> <urn:p> <urn:o> )>> a concon:StatedTriple .
            }
        "#).unwrap().commit().unwrap();
    // Query for the annotation
    // Assert: returns concon:StatedTriple
}

Integration tests

#[tokio::test]
async fn test_sparql_endpoint_after_upgrade() {
    // Create test server with new Oxigraph
    // Create dataset via API, insert data, query via /_ds/ endpoint
    // Verify correct SPARQL results JSON
}

#[tokio::test]
async fn test_existing_tests_pass() {
    // All 30 existing tests must pass without modification
    // (beyond API migration changes)
}

Manual tests (on dev.kg.degu.cl)

  1. Deploy upgraded binary to dev instance
  2. Verify automatic database migration completes without errors
  3. Create a dataset, insert triples, query via YASGUI
  4. Upload a PDF, verify GROBID extraction populates metadata
  5. Verify team pages, file listings, user management all work
  6. Run SPARQL queries on file catalog endpoints

Risk

  • One-way database migration: if something breaks, must restore from backup
  • RDF 1.2 spec is a W3C working draft: syntax may change in future Oxigraph versions
  • YASGUI does not support RDF 1.2 syntax (Oxigraph issue #698)

References

# Summary Upgrade the Oxigraph dependency from 0.4.x to 0.5.x to gain RDF 1.2 support, performance improvements, and continued maintenance. # Blocked by None. # Blocks - [\#002 SHACL-driven entity editor](002-shacl-driven-entity-editor.org) (needs RDF 1.2 for stated/non-stated triple annotations) # Motivation - Oxigraph 0.4.x only receives critical fixes; 0.5.x is the actively maintained line. - RDF 1.2 support (`rdf:reifies`, quoted triples) is needed for the entity editor's stated/non-stated pattern. - Faster updates and bulk loading. - Reduced storage footprint. # Scope of changes ## Dependency bump ``` toml # Cargo.toml oxigraph = { version = "0.5", features = ["rdf-12"] } ``` ## API migration Every `Store.query()` and `Store.update()` call must be rewritten. Old API (0.4.x): ``` rust let results = store.query("SELECT * WHERE { ?s ?p ?o }")?; store.update("INSERT DATA { ... }")?; ``` New API (0.5.x): ``` rust let evaluator = store.query_evaluator(); let results = evaluator.prepare("SELECT * WHERE { ?s ?p ?o }")?.exec()?; let transaction = store.start_transaction()?; transaction.update("INSERT DATA { ... }")?; transaction.commit()?; ``` ## Affected files All files that call `store.query()` or `store.update()`: - `src/auth.rs` — all SPARQL queries for users, teams, permissions - `src/store.rs` — dataset metadata queries and updates - `src/migration.rs` — schema version queries and updates - `src/routes/web.rs` — SPARQL updates for team/user/dataset creation - `src/routes/files.rs` — file catalog queries and updates - `src/routes/sparql.rs` — SPARQL endpoint handlers - `src/grobid.rs` — metadata update after extraction - `src/bin/*.rs` — CLI tools ## Model type changes - `Subject` enum merged into `NamedOrBlankNode` - `EvaluationError` split into `QueryEvaluationError` and `UpdateEvaluationError` - `QueryResults` now carries a lifetime parameter ## Database migration Oxigraph 0.5.x automatically migrates 0.4.x databases on first open. This is a one-way migration — databases cannot be reopened with 0.4.x. Procedure: 1. Backup data directory 2. Build with Oxigraph 0.5.x 3. Start the application (triggers automatic migration) ## Build requirements - Rust 1.87+ - C++20 compiler (GCC 14 on Debian 13) Both are available on the deployment server (degu03). # Tests ## Unit tests ``` rust #[test] fn test_store_query_new_api() { // Verify the new SparqlEvaluator API returns results let store = Store::new().unwrap(); store.start_transaction().unwrap() .update("INSERT DATA { <urn:s> <urn:p> <urn:o> }") .unwrap().commit().unwrap(); let results = store.query_evaluator() .prepare("SELECT * WHERE { ?s ?p ?o }").unwrap() .exec().unwrap(); // Assert one result } #[test] fn test_store_update_transaction() { // Verify transaction commit persists, rollback discards let store = Store::new().unwrap(); let tx = store.start_transaction().unwrap(); tx.update("INSERT DATA { <urn:s> <urn:p> <urn:o> }").unwrap(); tx.commit().unwrap(); // Assert triple exists let tx2 = store.start_transaction().unwrap(); tx2.update("INSERT DATA { <urn:a> <urn:b> <urn:c> }").unwrap(); drop(tx2); // rollback // Assert <urn:a> triple does NOT exist } #[test] fn test_rdf12_quoted_triples() { // Verify RDF 1.2 triple terms work with rdf-12 feature let store = Store::new().unwrap(); store.start_transaction().unwrap() .update(r#" PREFIX concon: <https://concon.2mia.org/ontology#> INSERT DATA { <urn:s> <urn:p> <urn:o> . <<( <urn:s> <urn:p> <urn:o> )>> a concon:StatedTriple . } "#).unwrap().commit().unwrap(); // Query for the annotation // Assert: returns concon:StatedTriple } ``` ## Integration tests ``` rust #[tokio::test] async fn test_sparql_endpoint_after_upgrade() { // Create test server with new Oxigraph // Create dataset via API, insert data, query via /_ds/ endpoint // Verify correct SPARQL results JSON } #[tokio::test] async fn test_existing_tests_pass() { // All 30 existing tests must pass without modification // (beyond API migration changes) } ``` ## Manual tests (on dev.kg.degu.cl) 1. Deploy upgraded binary to dev instance 2. Verify automatic database migration completes without errors 3. Create a dataset, insert triples, query via YASGUI 4. Upload a PDF, verify GROBID extraction populates metadata 5. Verify team pages, file listings, user management all work 6. Run SPARQL queries on file catalog endpoints # Risk - One-way database migration: if something breaks, must restore from backup - RDF 1.2 spec is a W3C working draft: syntax may change in future Oxigraph versions - YASGUI does not support RDF 1.2 syntax (Oxigraph issue \#698) # References - [Oxigraph CHANGELOG](https://github.com/oxigraph/oxigraph/blob/main/CHANGELOG.md) - [W3C RDF 1.2 Concepts (working draft)](https://www.w3.org/TR/rdf12-concepts/)
Author
Owner

Summary

Oxigraph has been upgraded from 0.4.x to 0.5.6 with the rdf-12 feature enabled. All deprecated API calls have been migrated to the new SparqlEvaluator interface, and all existing tests continue to pass alongside three new tests.

What changed

Dependency (Cargo.toml)

- oxigraph = "0.4"
+ oxigraph = { version = "0.5", features = ["rdf-12"] }

API migration

The deprecated Store::query() and Store::update() methods were replaced throughout the codebase. Two helper functions were added to src/store.rs to keep call sites concise:

  • sparql_query(store, query) — wraps SparqlEvaluator::new().parse_query().on_store().execute()
  • sparql_update(store, update) — wraps SparqlEvaluator::new().parse_update().on_store().execute()

The removed QueryResults::write() method in routes/sparql.rs was replaced with the new QueryResultsSerializer API, handling Boolean, Solutions, and Graph result types explicitly.

Files modified (13 total)

  • Cargo.toml, Cargo.lock — dependency bump
  • src/store.rs — helper functions + 3 new unit tests
  • src/auth.rs — migrated ~25 query/update call sites
  • src/migration.rs — migrated ~6 call sites
  • src/routes/sparql.rs — migrated queries/updates + new serializer
  • src/routes/files.rs — migrated ~8 call sites
  • src/routes/web.rs — migrated ~7 update call sites
  • src/bin/reset_password.rs — migrated
  • src/bin/add_members.rs — migrated
  • src/bin/fix_dataset_name.rs — migrated
  • src/bin/fix_users.rs — migrated
  • src/bin/migrate_team_ownership.rs — migrated

Clippy fixes

Three pre-existing clippy errors ("this loop never actually loops") were fixed in auth.rs and routes/files.rs by replacing for solution in solutions.flatten() { return ...; } with if let Some(solution) = solutions.flatten().next() { return ...; }.

All remaining clippy warnings were also resolved:

  • Auto-fixed: map_or simplified to is_some_and, collapsed if statements, div_ceil usage, Default impl for SessionStore, unused imports and variables.
  • Suppressed field_reassign_with_default in grobid.rs (deliberate pattern for structs with many fields).
  • Suppressed dead_code for functions used only by binary targets or tests (migration functions, test constructors, etc.).

New tests

Three unit tests were added to src/store.rs:

  1. test_store_query_new_api — verifies the SparqlEvaluator query path returns correct results.
  2. test_store_update_transaction — verifies that committed transactions persist and dropped transactions roll back.
  3. test_rdf12_quoted_triples — loads RDF 1.2 reified triples via Turtle I/O and verifies the rdf-12 feature stores them correctly.

Test results

All 33 tests pass (30 existing + 3 new). cargo fmt and cargo clippy produce zero warnings.

Notes

  • The rdf-12 feature currently enables triple term support in the Turtle I/O layer (oxttl) and storage layer, but SPARQL parsing (spargebra) does not yet support the <<( s p o )>> triple term syntax. The reified triple syntax << s p o >> works for loading via Turtle.
  • Database migration from 0.4.x to 0.5.x is automatic and one-way (Oxigraph handles this on first open). A backup should be taken before deploying.

Branch

issue/001-oxigraph-upgrade (3 commits)

# Summary Oxigraph has been upgraded from 0.4.x to 0.5.6 with the `rdf-12` feature enabled. All deprecated API calls have been migrated to the new `SparqlEvaluator` interface, and all existing tests continue to pass alongside three new tests. # What changed ## Dependency (Cargo.toml) ``` example - oxigraph = "0.4" + oxigraph = { version = "0.5", features = ["rdf-12"] } ``` ## API migration The deprecated `Store::query()` and `Store::update()` methods were replaced throughout the codebase. Two helper functions were added to `src/store.rs` to keep call sites concise: - `sparql_query(store, query)` — wraps `SparqlEvaluator::new().parse_query().on_store().execute()` - `sparql_update(store, update)` — wraps `SparqlEvaluator::new().parse_update().on_store().execute()` The removed `QueryResults::write()` method in `routes/sparql.rs` was replaced with the new `QueryResultsSerializer` API, handling Boolean, Solutions, and Graph result types explicitly. ## Files modified (13 total) - `Cargo.toml`, `Cargo.lock` — dependency bump - `src/store.rs` — helper functions + 3 new unit tests - `src/auth.rs` — migrated ~25 query/update call sites - `src/migration.rs` — migrated ~6 call sites - `src/routes/sparql.rs` — migrated queries/updates + new serializer - `src/routes/files.rs` — migrated ~8 call sites - `src/routes/web.rs` — migrated ~7 update call sites - `src/bin/reset_password.rs` — migrated - `src/bin/add_members.rs` — migrated - `src/bin/fix_dataset_name.rs` — migrated - `src/bin/fix_users.rs` — migrated - `src/bin/migrate_team_ownership.rs` — migrated ## Clippy fixes Three pre-existing clippy errors ("this loop never actually loops") were fixed in `auth.rs` and `routes/files.rs` by replacing `for solution in solutions.flatten() { return ...; }` with `if let Some(solution) = solutions.flatten().next() { return ...; }`. All remaining clippy warnings were also resolved: - Auto-fixed: `map_or` simplified to `is_some_and`, collapsed `if` statements, `div_ceil` usage, `Default` impl for `SessionStore`, unused imports and variables. - Suppressed `field_reassign_with_default` in `grobid.rs` (deliberate pattern for structs with many fields). - Suppressed `dead_code` for functions used only by binary targets or tests (migration functions, test constructors, etc.). # New tests Three unit tests were added to `src/store.rs`: 1. `test_store_query_new_api` — verifies the SparqlEvaluator query path returns correct results. 2. `test_store_update_transaction` — verifies that committed transactions persist and dropped transactions roll back. 3. `test_rdf12_quoted_triples` — loads RDF 1.2 reified triples via Turtle I/O and verifies the `rdf-12` feature stores them correctly. # Test results All 33 tests pass (30 existing + 3 new). `cargo fmt` and `cargo clippy` produce zero warnings. # Notes - The `rdf-12` feature currently enables triple term support in the Turtle I/O layer (`oxttl`) and storage layer, but SPARQL parsing (`spargebra`) does not yet support the `<<( s p o )>>` triple term syntax. The reified triple syntax `<< s p o >>` works for loading via Turtle. - Database migration from 0.4.x to 0.5.x is automatic and one-way (Oxigraph handles this on first open). A backup should be taken before deploying. # Branch `issue/001-oxigraph-upgrade` (3 commits)
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
daniel/concon#1
No description provided.