Skip to content

Commit

Permalink
GH-2006: fix handling of external bindings in FedX SingleSourceQuery (#…
Browse files Browse the repository at this point in the history
…2067)

This change correctly set externally passed binding to single source
queries, i.e. where the query is relevant at a single owner (and thus
the original query string is passed as-is)

Signed-off-by: Andreas Schwarte <[email protected]>
  • Loading branch information
aschwarte10 authored Apr 5, 2020
1 parent 80ad63a commit 7f26b87
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ public CloseableIteration<BindingSet, QueryEvaluationException> evaluateSingleSo
try {
Endpoint source = query.getSource();
return source.getTripleSource()
.getStatements(query.getQueryString(), query.getQueryInfo().getQueryType(), query.getQueryInfo());
.getStatements(query.getQueryString(), bindings, query.getQueryInfo().getQueryType(),
query.getQueryInfo());
} catch (RepositoryException | MalformedQueryException e) {
throw new QueryEvaluationException(e);
}
Expand Down Expand Up @@ -689,7 +690,8 @@ protected CloseableIteration<BindingSet, QueryEvaluationException> evaluateAtSta
Endpoint ownedEndpoint = federationContext.getEndpointManager()
.getEndpoint(statementSources.get(0).getEndpointID());
org.eclipse.rdf4j.federated.evaluation.TripleSource t = ownedEndpoint.getTripleSource();
result = t.getStatements(preparedQuery, EmptyBindingSet.getInstance(), null, queryInfo);
result = t.getStatements(preparedQuery, EmptyBindingSet.getInstance(), (FilterValueExpr) null,
queryInfo);
}

else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,30 @@ public CloseableIteration<BindingSet, QueryEvaluationException> getStatements(St
* @throws RepositoryException
* @throws MalformedQueryException
* @throws QueryEvaluationException
* @Deprecated will be removed in 4.0. Replaced with
* {@link #getStatements(String, BindingSet, QueryType, QueryInfo)}
*/
@Deprecated
public default CloseableIteration<BindingSet, QueryEvaluationException> getStatements(String preparedQuery,
QueryType queryType, QueryInfo queryInfo)
throws RepositoryException, MalformedQueryException, QueryEvaluationException {
return getStatements(preparedQuery, EmptyBindingSet.getInstance(), queryType, queryInfo);
}

/**
* Evaluate a given SPARQL query of the provided query type at the given source.
*
* @param preparedQuery
* @param queryBindings optional query bindings, use {@link EmptyBindingSet} if there are none
* @param queryType
* @param queryInfo
* @return the statements
* @throws RepositoryException
* @throws MalformedQueryException
* @throws QueryEvaluationException
*/
public CloseableIteration<BindingSet, QueryEvaluationException> getStatements(String preparedQuery,
BindingSet queryBindings,
QueryType queryType, QueryInfo queryInfo)
throws RepositoryException, MalformedQueryException, QueryEvaluationException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.Binding;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.BooleanQuery;
import org.eclipse.rdf4j.query.GraphQuery;
Expand Down Expand Up @@ -59,7 +60,7 @@ public TripleSourceBase(FederationContext federationContext, Endpoint endpoint)

@Override
public CloseableIteration<BindingSet, QueryEvaluationException> getStatements(
String preparedQuery, QueryType queryType, QueryInfo queryInfo)
String preparedQuery, BindingSet queryBindings, QueryType queryType, QueryInfo queryInfo)
throws RepositoryException, MalformedQueryException,
QueryEvaluationException {

Expand All @@ -68,13 +69,15 @@ public CloseableIteration<BindingSet, QueryEvaluationException> getStatements(
case SELECT:
monitorRemoteRequest();
TupleQuery tQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, preparedQuery);
applyBindings(tQuery, queryBindings);
applyMaxExecutionTimeUpperBound(tQuery);
configureInference(tQuery, queryInfo);
resultHolder.set(tQuery.evaluate());
return;
case CONSTRUCT:
monitorRemoteRequest();
GraphQuery gQuery = conn.prepareGraphQuery(QueryLanguage.SPARQL, preparedQuery);
applyBindings(gQuery, queryBindings);
applyMaxExecutionTimeUpperBound(gQuery);
configureInference(gQuery, queryInfo);
resultHolder.set(new GraphToBindingSetConversionIteration(gQuery.evaluate()));
Expand All @@ -84,6 +87,7 @@ public CloseableIteration<BindingSet, QueryEvaluationException> getStatements(
boolean hasResults = false;
try (RepositoryConnection _conn = conn) {
BooleanQuery bQuery = _conn.prepareBooleanQuery(QueryLanguage.SPARQL, preparedQuery);
applyBindings(bQuery, queryBindings);
applyMaxExecutionTimeUpperBound(bQuery);
configureInference(bQuery, queryInfo);
hasResults = bQuery.evaluate();
Expand All @@ -96,6 +100,15 @@ public CloseableIteration<BindingSet, QueryEvaluationException> getStatements(
});
}

private void applyBindings(Operation operation, BindingSet queryBindings) {
if (queryBindings == null) {
return;
}
for (Binding b : queryBindings) {
operation.setBinding(b.getName(), b.getValue());
}
}

@Override
public boolean hasStatements(Resource subj,
IRI pred, Value obj, QueryInfo queryInfo, Resource... contexts) throws RepositoryException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
import java.util.List;
import java.util.Set;

import org.eclipse.rdf4j.common.iteration.Iterations;
import org.eclipse.rdf4j.federated.endpoint.Endpoint;
import org.eclipse.rdf4j.federated.structures.FedXDataset;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.BooleanQuery;
import org.eclipse.rdf4j.query.GraphQuery;
import org.eclipse.rdf4j.query.GraphQueryResult;
import org.eclipse.rdf4j.query.QueryResults;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
Expand All @@ -23,6 +27,8 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.google.common.collect.Sets;

public class BasicTests extends SPARQLBaseTest {

@Test
Expand Down Expand Up @@ -207,4 +213,38 @@ public void testBeginTransaction() throws Exception {
Repositories.tupleQuery(fedxRule.repository, "SELECT ?person WHERE { ?person ?p 'Alan' }",
it -> QueryResults.asList(it)).size());
}

@Test
public void testSingleSource_SetBinding() throws Exception {

/* test a single source select query where we set a binding */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));

try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {

// SELECT query
TupleQuery tq = conn
.prepareTupleQuery("SELECT ?person WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name }");
tq.setBinding("name", l("Alan"));
TupleQueryResult tqr = tq.evaluate();
List<BindingSet> res = Iterations.asList(tqr);
assertContainsAll(res, "person", Sets.newHashSet(iri("http://example.org/", "a")));

// CONSTRUCT query
GraphQuery gq = conn.prepareGraphQuery(
"CONSTRUCT { ?person <http://xmlns.com/foaf/0.1/name> ?name } WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name }");
gq.setBinding("name", l("Alan"));
GraphQueryResult gqr = gq.evaluate();
List<Statement> stmts = Iterations.asList(gqr);
Assertions.assertEquals(1, stmts.size());
Assertions.assertEquals(iri("http://example.org/", "a"), stmts.get(0).getSubject());

// BOOLEAN query
BooleanQuery bq = conn.prepareBooleanQuery("ASK { ?person <http://xmlns.com/foaf/0.1/name> ?name }");
bq.setBinding("name", l("non-existing-name"));
Assertions.assertEquals(false, bq.evaluate());

}

}
}

0 comments on commit 7f26b87

Please sign in to comment.