RYA-41 Fixed a bug where AccumuloIndexSet assumes the first node of a ParsedQuery is always a Projection node.
Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/8db5bbc3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/8db5bbc3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/8db5bbc3 Branch: refs/heads/develop Commit: 8db5bbc3aa0256426c1c9ec925a31bf9e177ff3b Parents: 3157bc4 Author: Kevin Chilton <[email protected]> Authored: Fri Feb 19 17:22:15 2016 -0500 Committer: Kevin Chilton <[email protected]> Committed: Fri Feb 19 17:22:15 2016 -0500 ---------------------------------------------------------------------- .../external/tupleSet/AccumuloIndexSet.java | 9 ++- .../external/tupleSet/ParsedQueryUtil.java | 60 ++++++++++++++++++ .../external/tupleSet/ParsedQueryUtilTest.java | 67 ++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8db5bbc3/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/AccumuloIndexSet.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/AccumuloIndexSet.java b/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/AccumuloIndexSet.java index 456c465..9c1bc7b 100644 --- a/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/AccumuloIndexSet.java +++ b/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/AccumuloIndexSet.java @@ -58,6 +58,7 @@ import org.openrdf.query.parser.sparql.SPARQLParser; import org.openrdf.sail.SailException; import com.google.common.base.Joiner; +import com.google.common.base.Optional; import com.google.common.collect.HashBiMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -123,7 +124,13 @@ public class AccumuloIndexSet extends ExternalTupleSet implements ExternalBatchi this.accCon = accCon; final SPARQLParser sp = new SPARQLParser(); final ParsedTupleQuery pq = (ParsedTupleQuery) sp.parseQuery(sparql, null); - setProjectionExpr((Projection) pq.getTupleExpr()); + + Optional<Projection> projection = new ParsedQueryUtil().findProjection(pq); + if(!projection.isPresent()) { + throw new MalformedQueryException("SPARQL query '" + sparql + "' does not contain a Projection."); + } + setProjectionExpr(projection.get()); + Set<VariableOrder> orders = null; try { orders = pcj.getPcjMetadata(accCon, tablename).getVarOrders(); http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8db5bbc3/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtil.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtil.java b/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtil.java new file mode 100644 index 0000000..b41c9c9 --- /dev/null +++ b/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtil.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.indexing.external.tupleSet; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.concurrent.atomic.AtomicReference; + +import javax.annotation.ParametersAreNonnullByDefault; + +import org.openrdf.query.algebra.Projection; +import org.openrdf.query.algebra.helpers.QueryModelVisitorBase; +import org.openrdf.query.parser.ParsedQuery; + +import com.google.common.base.Optional; + +/** + * Utilities that help applications inspect {@link ParsedQuery} objects. + */ +@ParametersAreNonnullByDefault +public class ParsedQueryUtil { + + /** + * Finds the first {@link Projection} node within a {@link ParsedQuery}. + * + * @param query - The query that will be searched. (not null) + * @return The first projection encountered if the query has one; otherwise absent. + */ + public Optional<Projection> findProjection(final ParsedQuery query) { + checkNotNull(query); + + // When a projection is encountered for the requested index, store it in atomic reference and quit searching. + final AtomicReference<Projection> projectionRef = new AtomicReference<>(); + + query.getTupleExpr().visit(new QueryModelVisitorBase<RuntimeException>() { + @Override + public void meet(Projection projection) { + projectionRef.set(projection); + } + }); + + return Optional.fromNullable( projectionRef.get() ); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8db5bbc3/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtilTest.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtilTest.java b/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtilTest.java new file mode 100644 index 0000000..d3755b3 --- /dev/null +++ b/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/ParsedQueryUtilTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.indexing.external.tupleSet; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openrdf.query.MalformedQueryException; +import org.openrdf.query.algebra.Projection; +import org.openrdf.query.parser.ParsedQuery; +import org.openrdf.query.parser.sparql.SPARQLParser; + +import com.google.common.base.Optional; + +/** + * Tests the methods of {@link ParsedQueryUtil}. + */ +public class ParsedQueryUtilTest { + + @Test + public void findProjection_distinctIsTopNode() throws MalformedQueryException { + // A SPARQL query that uses the DISTINCT keyword. + String sparql = + "SELECT DISTINCT ?a ?b " + + "WHERE {" + + "?a <http://talksTo> ?b" + + "}"; + + // Run the test. + SPARQLParser parser = new SPARQLParser(); + ParsedQuery query = parser.parseQuery(sparql, null); + Optional<Projection> projection = new ParsedQueryUtil().findProjection(query); + assertTrue(projection.isPresent()); + } + + @Test + public void findProjection_projectionIsTopNode() throws MalformedQueryException { + // A SPARQL query that will result in the Projection node being the top node. + String sparql = + "SELECT ?a ?b " + + "WHERE {" + + "?a <http://talksTo> ?b" + + "}"; + + // Run the test. + SPARQLParser parser = new SPARQLParser(); + ParsedQuery query = parser.parseQuery(sparql, null); + Optional<Projection> projection = new ParsedQueryUtil().findProjection(query); + assertTrue(projection.isPresent()); + } +} \ No newline at end of file
