shawnsmith opened a new issue, #2650:
URL: https://github.com/apache/jena/issues/2650

   ### Version
   
   5.1.0
   
   ### What happened?
   
   https://github.com/apache/jena/issues/2028 deprecated 
`QueryExecutionDatasetBuilder.initialBinding()` and 
https://github.com/apache/jena/issues/2435 deprecated it for removal. But the 
`substitution()` method isn't a perfect replacement for `initialBinding()`. I 
ran across an edge case where `initialBinding()` appears to work correctly but 
`substitution()` does not:
   
   Substitute `?a <- 123` in this query:
   ```sparql
   PREFIX : <https://example.com/>
   SELECT (SUM(?a + ?b) AS ?c)
   WHERE {
     ?s :p ?a ;
        :q ?b .
   }
   ```
   and you get this, where `?a` in the aggregation expression is not defined:
   ```sparql
   PREFIX  :     <https://example.com/>
   SELECT  (SUM(( ?a + ?b )) AS ?c)
   WHERE
     { ?s  :p  123 ;
           :q  ?b
     }
   ```
   
   It looks like `substitution()` doesn't replace variable references in 
aggregation expressions. I don't know if that's a bug or intended. For now I'm 
sticking with `initialBinding()`, so I'm concerned that it's marked for removal.
   
   ### Relevant output and stacktrace
   
   ```shell
   package jena_test;
   
   import org.apache.jena.datatypes.xsd.XSDDatatype;
   import org.apache.jena.graph.Graph;
   import org.apache.jena.graph.Node;
   import org.apache.jena.query.Query;
   import org.apache.jena.query.QueryFactory;
   import org.apache.jena.riot.Lang;
   import org.apache.jena.sparql.core.Var;
   import org.apache.jena.sparql.engine.binding.Binding;
   import org.apache.jena.sparql.engine.binding.BindingBuilder;
   import org.apache.jena.sparql.exec.QueryExec;
   import org.apache.jena.sparql.graph.GraphFactory;
   import org.apache.jena.sparql.resultset.ResultsWriter;
   import org.apache.jena.sparql.syntax.syntaxtransform.QueryTransformOps;
   import org.junit.jupiter.api.Test;
   
   import java.io.ByteArrayOutputStream;
   import java.util.Map;
   
   import static java.nio.charset.StandardCharsets.UTF_8;
   import static org.apache.jena.graph.NodeFactory.createLiteralByValue;
   import static org.apache.jena.graph.NodeFactory.createURI;
   import static org.junit.jupiter.api.Assertions.assertEquals;
   
   class AggregationSubstitutionTest {
       @Test
       void testSubstitution_Aggregation() {
           // Current versions of Jena strongly recommend using 
`QueryExecBuilder.substitution(Binding)` instead of
           // `QueryExecDatasetBuilder.initialBinding(Binding), even to the 
point of marking the `initialBinding()`
           // method deprecated. But the two methods aren't equivalent, as 
shown in the following query:
   
           String sparql = """
                   PREFIX : <https://example.com/>
                   SELECT (SUM(?a + ?b) AS ?c)
                   WHERE {
                     ?s :p ?a ;
                        :q ?b .
                   }
                   """;
           Map<Var, Node> params = Map.of(
                   Var.alloc("d"), createURI("https://example.com/Bar";),
                   Var.alloc("a"), createLiteralByValue(123, 
XSDDatatype.XSDinteger));
   
           // Note: QueryExecDatasetBuilder.build() implements substitutionMap 
using QueryTransformOps.transform().
           Query transformed = 
QueryTransformOps.transform(QueryFactory.create(sparql), params);
   
           // Note: substitution results in ?a being undefined in the SUM 
expression!
           assertEquals("""
                   PREFIX  :     <https://example.com/>
                   SELECT  (SUM(( ?a + ?b )) AS ?c)
                   WHERE
                     { ?s  :p  123 ;
                           :q  ?b
                     }
                   """, transformed.toString());
           QueryFactory.create(transformed.toString());
   
           String ns = "https://example.com/";;
           Graph graph = GraphFactory.createDefaultGraph();
           graph.add(createURI(ns + "Bar"), createURI(ns + "p"), 
createLiteralByValue(123, XSDDatatype.XSDinteger));
           graph.add(createURI(ns + "Bar"), createURI(ns + "q"), 
createLiteralByValue(456, XSDDatatype.XSDinteger));
   
           run(sparql, graph, params);
       }
   
       private static void run(String sparql, Graph graph, Map<Var, Node> 
params) {
           BindingBuilder builder = Binding.builder();
           params.forEach(builder::add);
           Binding binding = builder.build();
   
           // Use substitution()
           ByteArrayOutputStream buf1 = new ByteArrayOutputStream();
           try (QueryExec qe1 = 
QueryExec.graph(graph).query(sparql).substitution(binding).build()) {
               ResultsWriter.create().lang(Lang.CSV).write(buf1, qe1.select());
           }
           String csv1 = buf1.toString(UTF_8);
           System.out.println("substitution:\n" + csv1.trim());
   
           // Use initialBinding()
           ByteArrayOutputStream buf2 = new ByteArrayOutputStream();
           try (QueryExec qe2 = 
QueryExec.newBuilder().graph(graph).query(sparql).initialBinding(binding).build())
 {
               ResultsWriter.create().lang(Lang.CSV).write(buf2, qe2.select());
           }
           String csv2 = buf2.toString(UTF_8);
           System.out.println("initialBinding:\n" + csv2.trim());
   
           assertEquals(csv1, csv2, "Query results should be the same");
       }
   }
   ```
   
   
   ### Are you interested in making a pull request?
   
   None


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to