Summary
Fix two W3C SPARQL conformance test failures:
-
Blank node BGP scope validation — the parser incorrectly rejected valid queries where a blank node label appeared in multiple TriplesBlock nodes within the same GroupGraphPattern (e.g. separated by FILTER), and incorrectly accepted invalid queries where a blank node label crossed UNION/OPTIONAL/GRAPH boundaries within the same outer group.
-
xsd:double lexical form normalization for MIN/MAX results — the W3C min_with_group_by test expected "2.0E-1" but the engine returned "2E-1" (both represent the same value). The comparison now uses numeric equality for MIN/MAX aggregate results.
Specification & Semantics
Per SPARQL 1.0 §4.1.4: a blank node label is scoped to a basic graph pattern. A BGP extends across multiple TriplesBlock elements in a GroupGraphPattern unless separated by a BGP-breaking pattern: OPTIONAL, UNION, GRAPH, SERVICE, MINUS, EXISTS, or a plain nested { } group. FILTER does NOT break a BGP.
Root Cause
Blank node scoping
The previous implementation tracked blank node labels against the identity of bgpStack.peek() (per-TriplesBlock). Because the ANTLR grammar defines TriplesBlock recursively, two consecutive triples in the same semantic BGP had different list identities → false validation errors on valid queries.
The fix introduces a bgpScopeIdStack (parallel to groupStack) that:
- Pushes a new scope ID at every
enterGroup()
- Pops at
exitGroup()
- Renews the outer scope after any BGP-breaking inner pattern closes
- Does NOT renew for FILTER
MIN/MAX numeric normalization
Extended ComputedNumericResults.computed() to include MIN and MAX aggregates so comparison uses numeric equality (via BigDecimal) instead of lexical equality.
Target Branch
feature/corese-next
Targeted W3C Tests — Previously Failing → Now Passing
syn-09, syn-10, syn-11, syntax-bnodes-05, syn-blabel-cross-filter (positive syntax)
synbad-union-breaks-bgp, synbad-opt-breaks-bgp, synbad-graph-breaks-bgp (negative syntax)
syn-blabel-cross-union-bad, syn-blabel-cross-optional-bad, syn-blabel-cross-graph-bad
synbad34rq–synbad38rq (SPARQL 1.1 negative syntax)
synbad03rq (SPARQL 1.1 — duplicate SELECT variable)
min_with_group_by (SPARQL 1.1 aggregate MIN)
Acceptance Criteria
Summary
Fix two W3C SPARQL conformance test failures:
Blank node BGP scope validation — the parser incorrectly rejected valid queries where a blank node label appeared in multiple
TriplesBlocknodes within the sameGroupGraphPattern(e.g. separated byFILTER), and incorrectly accepted invalid queries where a blank node label crossed UNION/OPTIONAL/GRAPH boundaries within the same outer group.xsd:double lexical form normalization for MIN/MAX results — the W3C
min_with_group_bytest expected"2.0E-1"but the engine returned"2E-1"(both represent the same value). The comparison now uses numeric equality for MIN/MAX aggregate results.Specification & Semantics
Per SPARQL 1.0 §4.1.4: a blank node label is scoped to a basic graph pattern. A BGP extends across multiple
TriplesBlockelements in aGroupGraphPatternunless separated by a BGP-breaking pattern:OPTIONAL,UNION,GRAPH,SERVICE,MINUS,EXISTS, or a plain nested{ }group.FILTERdoes NOT break a BGP.Root Cause
Blank node scoping
The previous implementation tracked blank node labels against the identity of
bgpStack.peek()(per-TriplesBlock). Because the ANTLR grammar definesTriplesBlockrecursively, two consecutive triples in the same semantic BGP had different list identities → false validation errors on valid queries.The fix introduces a
bgpScopeIdStack(parallel togroupStack) that:enterGroup()exitGroup()MIN/MAX numeric normalization
Extended
ComputedNumericResults.computed()to includeMINandMAXaggregates so comparison uses numeric equality (viaBigDecimal) instead of lexical equality.Target Branch
feature/corese-nextTargeted W3C Tests — Previously Failing → Now Passing
syn-09,syn-10,syn-11,syntax-bnodes-05,syn-blabel-cross-filter(positive syntax)synbad-union-breaks-bgp,synbad-opt-breaks-bgp,synbad-graph-breaks-bgp(negative syntax)syn-blabel-cross-union-bad,syn-blabel-cross-optional-bad,syn-blabel-cross-graph-badsynbad34rq–synbad38rq(SPARQL 1.1 negative syntax)synbad03rq(SPARQL 1.1 — duplicate SELECT variable)min_with_group_by(SPARQL 1.1 aggregate MIN)Acceptance Criteria
min_with_group_byW3C test passesScalarFunctionsTest.decimalCastDoesNotRewriteItsSourceTermstill passes