(R2RML) Error on Colliding TriplesMap IRIs & Report Table Count - #1401
Merged
Conversation
Phase 2 (hardening): MappingExtractor::extract_all now rejects a mapping where two or more rr:TriplesMap subjects resolve to the same IRI. Such a collapse (classically an idiomatic relative <#fragment> subject resolved against @base) previously merged silently -- first-wins logical table and subject map, union of every predicate-object map -- yielding plausible-but-wrong triples that scan only the first table. The collision is now a hard R2rmlError::DuplicateTriplesMap. Phase 3 (reporting): R2rmlCreateResult gains table_count and table_names, populated from the compiled mapping on both the CAS-stored and address-validated paths. `fluree iceberg map` now prints `Tables: N (DW.X, DW.Y, ...)` alongside `TriplesMaps: N` for local and remote output, so mapping a 16-table star schema visibly shows 16 tables, not 1. The /iceberg/map server response carries the new fields for remote parity. Tests: an idiomatic `@base <http://ex/edw>` + `<#DimX>`/`<#FactY>` multi-table fixture asserts N distinct TriplesMaps over N distinct tables and that a non-first map scans its own table rather than the first map's; a hardening test asserts a colliding-IRI document errors. Phase 1 (Turtle parser fragment fix) is on the base branch; Phase 4 (operator index wiring) is deferred. Refs #1395
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is Phases 2 & 3 of issue #1395 — the R2RML half of the multi-table
collapse fix, layered on top of PR-1's Turtle parser fragment fix.
TriplesMapcollapse impossible.When two or more
rr:TriplesMapsubjects resolve to the same IRI, the extractornow returns a hard error instead of merging them (first-wins logical table /
subject map, union of every predicate-object map) into plausible-but-wrong data.
create result and
fluree iceberg mapnow reportTables: N (names…)next toTriplesMaps: N, so a 16-table star schema that has silently collapsed showsTables: 1immediately rather than failing mysteriously at query time.Phase 1 (the parser fix) is the base branch. Phase 4 (wiring the operator's
prebuilt
find_maps_for_*selection indexes for O(1) map selection) isintentionally deferred and out of scope here.
What changed
Phase 2 — collapse is now a hard error
fluree-db-r2rml/src/loader/extractor.rs—MappingExtractor::extract_all:rr:TriplesMapIRI is extracted exactly once (a repeateda rr:TriplesMaptriple for an already-seen subject is harmless redundancy andis skipped).
ensure_no_collisionguard counts therr:logicalTableand
rr:subjectMapedges on the subject. A well-formed TriplesMap has exactlyone of each; more than one is the signature of two definitions merged onto one
IRI, and is now rejected with
R2rmlError::DuplicateTriplesMap. This signal isindependent of graph bag/set semantics (the merged subject always carries the
distinct logical-table blank nodes) and produces no false positive for a
redundant type triple on a single well-formed map.
fluree-db-r2rml/src/error.rs— newR2rmlError::DuplicateTriplesMap(String)variant whose message names the colliding IRI and points at the usual cause
(relative
<#fragment>subjects collapsing against@base).Phase 3 —
Tables: N (…)at registrationfluree-db-api/src/graph_source/result.rs—R2rmlCreateResultgainstable_count: usizeandtable_names: Vec<String>(sorted, distinct).fluree-db-api/src/graph_source/r2rml.rs— both the CAS-stored(
R2rmlMappingInput::Content) and address-validated(
R2rmlMappingInput::Address) paths now derive the table list from the compiledmapping via a small
sorted_table_nameshelper;validate_r2rml_mapping_from_addressreturns
(count, table_names).fluree-db-cli/src/commands/iceberg.rs— printsTables: N (DW.X, DW.Y, …)afterTriplesMaps:on both the local andremote (
fluree iceberg map) output paths, via a sharedformat_table_summaryhelper (falls back to bare
Nwhen no names are available, e.g. an unvalidatedaddress mapping).
fluree-db-server/src/routes/iceberg.rs— the/iceberg/mapJSON response(
IcebergMapResponse) carries optionaltable_count/table_namesso theremote CLI path renders the same line. No behavior change for the raw (non-R2RML)
Iceberg branch.
Tests added
In
fluree-db-api/tests/it_graph_source_r2rml.rs:test_base_fragment_multi_table_compiles_to_distinct_tables— the offlineregression guard. An idiomatic
@base <http://ex/edw>+<#DimDate>/<#DimProduct>/<#FactSales>fixture compiles to 3 distinct TriplesMaps(
…edw#DimDate,…edw#DimProduct,…edw#FactSales) over 3 distinct tables(
DW.DIM_DATE,DW.DIM_PRODUCT,DW.FACT_SALES) — not one merged map.engine_e2e_base_fragment_scans_non_first_table— drives the engine with arecording provider (the
MultiTableMockProviderpattern). Querying a predicateowned only by the non-first map scans
DW.DIM_PRODUCTand neverDW.DIM_DATE(the first map's table — the exact collapse symptom), returning thecorrect rows.
test_colliding_triples_map_iris_error— the Phase-2 hardening test: a documentwith two
rr:TriplesMapsubjects resolving to one IRI fails to compile with aDuplicate TriplesMap IRIerror naming the colliding subject.Results
cargo test -p fluree-db-r2rml— 46 passed, 0 failed (+1 doctest);--features turtle— 55 passed, 0 failed (+1 doctest).cargo test -p fluree-db-api --features iceberg— full suite green; the touchedbinary
it_graph_source_r2rmlis 32 passed, 0 failed (2 ignored — externalPolaris/MinIO), including the 3 new tests. No regressions across the rest of the
api suite (640 unit + all
grp_*/it_*integration binaries, 0 failures).cargo clippy -- -D warnings(all--all-targets) — clean onfluree-db-r2rml --features turtle,fluree-db-api --features iceberg,fluree-db-cli --features iceberg, andfluree-db-server.cargo fmt— applied.cargo check -p fluree-db-cli --features iceberg— clean.Risk / compatibility
was already silently corrupt (first-wins table + union projection); a loud error
is the correct, strictly-safer outcome. Only mappings that actually collide are
affected — distinct-IRI multi-table mappings (the norm) are untouched.
the server response fields are
skip_serializing_if = "Option::is_none", and theonly
R2rmlCreateResultconstructor is updated. The raw-Iceberg path isunchanged.
green.
Fixes #1395