Is there an existing issue for this?
Current Behavior
The Explorer SPARQL path (SparqlTranslator.translate_sparql_to_spark) translates SPARQL to Spark SQL with a regex pipeline. Valid SPARQL outside the supported subset can disappear from the generated SQL without an error. The SQL is executable but has different semantics from the submitted query.
Confirmed silent drops:
GROUP BY / aggregates
- numeric or complex
FILTER expressions (the parser never emits gt/lt/gte/lte, despite the docstring advertising FILTER(?var > value))
- property paths
A second, independent defect: relationship OPTIONAL patterns emit LEFT JOINs, then add {rel}.{col} IS NOT NULL predicates to the top-level WHERE. A single OPTIONAL becomes mandatory; multiple OPTIONALs are OR-joined, so the query requires at least one optional match.
The public /api/v1/query default (engine=local) is not an equivalent fallback: RDFLib queries the R2RML mapping graph, not warehouse data. Explorer (/dtwin/execute, /dtwin/translate) always uses the Spark translator with no RDFLib fallback.
Expected Behavior
- Valid-but-unsupported Spark SPARQL is rejected with
ValidationError before SQL generation (fail-closed). Messages identify the construct, e.g. Spark SPARQL does not support GROUP BY.
- The currently supported subset still translates (SELECT, DISTINCT, LIMIT, simple BGP, supported string FILTERs, literal BIND, specialized relationship UNION).
- Relationship OPTIONAL preserves unmatched primary rows (
LEFT JOIN without a top-level presence predicate). Unbound optional vars are NULL.
- Local RDFLib is not advertised as a warehouse-data fallback.
Steps To Reproduce
- Open Explorer SPARQL against a mapped domain with warehouse data.
- Run:
SELECT ?s WHERE { ?s a <http://example.org/Customer> } GROUP BY ?s
- Observe a successful SQL translation with no
GROUP BY (same for numeric FILTER and property paths).
- Run a relationship OPTIONAL:
SELECT ?c ?o WHERE {
?c a <http://example.org/Customer> .
OPTIONAL { ?c <http://example.org/hasOrder> ?o }
}
- Inspect generated SQL:
LEFT JOIN plus WHERE (rel.customer_id IS NOT NULL), which drops customers with no order.
Unit-level reproduction (no warehouse):
from back.core.w3c.sparql.SparqlTranslator import SparqlTranslator
# GROUP BY / FILTER / property path currently return success with incomplete SQL
# OPTIONAL currently emits WHERE (rel_o.customer_id IS NOT NULL)
Cloud
Azure
Browser
Chrome
OntoBricks Version
0.9.0
Relevant log output
# Example: GROUP BY query currently succeeds with incomplete SQL
SELECT t_s.customer_id AS s
FROM (SELECT * FROM test_catalog.test_schema.customers) AS t_s
WHERE 1=1 LIMIT 10
# Example: relationship OPTIONAL currently adds a presence filter
SELECT t_c.customer_id AS c, rel_o.order_id AS o
FROM ... LEFT JOIN (...) AS rel_o ON t_c.customer_id = rel_o.customer_id
WHERE (rel_o.customer_id IS NOT NULL)
LIMIT 10
Additional Context
Primary files
src/back/core/w3c/sparql/SparqlTranslator.py (_parse_value_filters ~505–611, _spark_finalize_query_sql ~2036–2041, OPTIONAL LEFT JOIN + optional_rel_conditions ~1813–1943)
src/back/core/w3c/sparql/DomainQueryService.py (local engine queries R2RML, not warehouse)
tests/back/core/w3c/sparql/test_sparql_translator_units.py (19 tests; 9 use if result.get("success") and can pass on failed translation)
Approved design (this issue)
docs/superpowers/specs/2026-09-11-spark-sparql-fail-closed-design.md
Scope: RDFLib algebra capability gate + OPTIONAL correction + test hardening. Non-goals: full SPARQL 1.1, numeric FILTER implementation, algebra-to-SQL rewrite, RDFLib fallback, SWRL/T-Box changes.
Related findings (separate follow-ups, not this issue)
- SWRL: negated built-ins silently skipped in
_build_negated_atoms; unbound vars become string literals
- Reasoning: no T-Box ↔ A-Box fixed-point; CWA/UNA from
NOT EXISTS under-documented
- Lint noise: claimed F821 locations are stale (0 on current tree); B904/F841 are hygiene
Acceptance
- Unsupported constructs raise
ValidationError instead of returning incomplete SQL
- Relationship OPTIONAL keeps unmatched rows
- Translator unit tests assert success unconditionally
- Docs state the Spark SPARQL subset and that local RDFLib is not a warehouse fallback
Is there an existing issue for this?
Current Behavior
The Explorer SPARQL path (
SparqlTranslator.translate_sparql_to_spark) translates SPARQL to Spark SQL with a regex pipeline. Valid SPARQL outside the supported subset can disappear from the generated SQL without an error. The SQL is executable but has different semantics from the submitted query.Confirmed silent drops:
GROUP BY/ aggregatesFILTERexpressions (the parser never emitsgt/lt/gte/lte, despite the docstring advertisingFILTER(?var > value))A second, independent defect: relationship
OPTIONALpatterns emitLEFT JOINs, then add{rel}.{col} IS NOT NULLpredicates to the top-levelWHERE. A single OPTIONAL becomes mandatory; multiple OPTIONALs are OR-joined, so the query requires at least one optional match.The public
/api/v1/querydefault (engine=local) is not an equivalent fallback: RDFLib queries the R2RML mapping graph, not warehouse data. Explorer (/dtwin/execute,/dtwin/translate) always uses the Spark translator with no RDFLib fallback.Expected Behavior
ValidationErrorbefore SQL generation (fail-closed). Messages identify the construct, e.g.Spark SPARQL does not support GROUP BY.LEFT JOINwithout a top-level presence predicate). Unbound optional vars are NULL.Steps To Reproduce
GROUP BY(same for numericFILTERand property paths).LEFT JOINplusWHERE (rel.customer_id IS NOT NULL), which drops customers with no order.Unit-level reproduction (no warehouse):
Cloud
Azure
Browser
Chrome
OntoBricks Version
0.9.0
Relevant log output
Additional Context
Primary files
src/back/core/w3c/sparql/SparqlTranslator.py(_parse_value_filters~505–611,_spark_finalize_query_sql~2036–2041, OPTIONAL LEFT JOIN +optional_rel_conditions~1813–1943)src/back/core/w3c/sparql/DomainQueryService.py(local engine queries R2RML, not warehouse)tests/back/core/w3c/sparql/test_sparql_translator_units.py(19 tests; 9 useif result.get("success")and can pass on failed translation)Approved design (this issue)
docs/superpowers/specs/2026-09-11-spark-sparql-fail-closed-design.mdScope: RDFLib algebra capability gate + OPTIONAL correction + test hardening. Non-goals: full SPARQL 1.1, numeric FILTER implementation, algebra-to-SQL rewrite, RDFLib fallback, SWRL/T-Box changes.
Related findings (separate follow-ups, not this issue)
_build_negated_atoms; unbound vars become string literalsNOT EXISTSunder-documentedAcceptance
ValidationErrorinstead of returning incomplete SQL