There is a bug in SparqlParser.php (parseGraphPattern) where it calls parseGraph on finding the GRAPH token, it doesn't pass on optional/union/subpattern details, and furthermore creates a second GraphPattern. As an example, for the query:
SELECT * {{ ?s ?p ?o } UNION {GRAPH ?g { ?s ?p ?o }}}
The parser will create the Query object like this:
Query Object
(
[resultPart:protected] => Array
(
[0] => GraphPattern Object
(
[graphname:protected] =>
[triplePatterns:protected] => Array()
[constraints:protected] => Array()
[optional:protected] =>
[union:protected] =>
[subpatternOf:protected] =>
[open] =>
[isConstructPattern] =>
[patternId] => 0
)
[1] => GraphPattern Object
(
[graphname:protected] =>
[triplePatterns:protected] => Array
(
[0] => QueryTriple Object
(
[subject:protected] => ?s
[predicate:protected] => ?p
[object:protected] => ?o
)
)
[constraints:protected] => Array()
[optional:protected] =>
[union:protected] =>
[subpatternOf:protected] => 0
[open] =>
[isConstructPattern] =>
[patternId] => 1
)
[2] => GraphPattern Object
(
[graphname:protected] =>
[triplePatterns:protected] => Array()
[constraints:protected] => Array()
[optional:protected] =>
[union:protected] => 1
[subpatternOf:protected] => 0
[open] =>
[isConstructPattern] =>
[patternId] => 2
)
[3] => GraphPattern Object
(
[graphname:protected] => ?g
[triplePatterns:protected] => Array
(
[0] => QueryTriple Object
(
[subject:protected] => ?s
[predicate:protected] => ?p
[object:protected] => ?o
)
)
[constraints:protected] => Array()
[optional:protected] =>
[union:protected] =>
[subpatternOf:protected] =>
[open] =>
[isConstructPattern] =>
[patternId] => 3
)
)
)
Where GraphPattern[2] has the correct union and subpattern values but the graph pattern got added to a new object [3] instead, which is missing the corresponding union/subpattern values.
The result (in this case) is an error when trying to join the results.