Repository: marmotta Updated Branches: refs/heads/develop a37fc2f96 -> fa8ef614e
fix MARMOTTA-552 (complex UNION with subquery) Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/fa8ef614 Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/fa8ef614 Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/fa8ef614 Branch: refs/heads/develop Commit: fa8ef614e2029d2a3d1eb27d756a968199e2ce94 Parents: a37fc2f Author: Sebastian Schaffert <[email protected]> Authored: Thu Oct 16 11:23:03 2014 +0200 Committer: Sebastian Schaffert <[email protected]> Committed: Thu Oct 16 11:23:03 2014 +0200 ---------------------------------------------------------------------- .../kiwi/sparql/builder/SQLBuilder.java | 2 +- .../marmotta/kiwi/sparql/builder/SQLUnion.java | 64 +++++++++++++++----- .../kiwi/sparql/test/KiWiSparqlJoinTest.java | 8 +++ .../marmotta/kiwi/sparql/test/query36.sparql | 33 ++++++++++ 4 files changed, 91 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/fa8ef614/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java index 1d92cd8..199b922 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java @@ -170,7 +170,7 @@ public class SQLBuilder { } private void prepareBuilder() throws UnsatisfiableQueryException { - Preconditions.checkArgument(query instanceof Union || query instanceof Extension || query instanceof Order || query instanceof Group || query instanceof LeftJoin ||query instanceof Join || query instanceof Filter || query instanceof StatementPattern || query instanceof Distinct || query instanceof Slice || query instanceof Reduced); + Preconditions.checkArgument(query instanceof Projection || query instanceof Union || query instanceof Extension || query instanceof Order || query instanceof Group || query instanceof LeftJoin ||query instanceof Join || query instanceof Filter || query instanceof StatementPattern || query instanceof Distinct || query instanceof Slice || query instanceof Reduced); // collect all patterns in a list, using depth-first search over the join http://git-wip-us.apache.org/repos/asf/marmotta/blob/fa8ef614/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLUnion.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLUnion.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLUnion.java index a87558a..26b7775 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLUnion.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLUnion.java @@ -21,6 +21,9 @@ import org.apache.marmotta.kiwi.persistence.KiWiDialect; import org.apache.marmotta.kiwi.sparql.exception.UnsatisfiableQueryException; import org.openrdf.query.BindingSet; import org.openrdf.query.Dataset; +import org.openrdf.query.algebra.Projection; +import org.openrdf.query.algebra.ProjectionElem; +import org.openrdf.query.algebra.TupleExpr; import org.openrdf.query.algebra.Union; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,39 +52,50 @@ public class SQLUnion extends SQLAbstractSubquery { public SQLUnion(String alias, Union query, BindingSet bindings, Dataset dataset, ValueConverter converter, KiWiDialect dialect) throws UnsatisfiableQueryException { super(alias); + Set<String> leftProjected = getProjectedVariables(query.getLeftArg()); + Set<String> rightProjected = getProjectedVariables(query.getRightArg()); + // we build a full subquery for each of the UNION's arguments - left = new SQLBuilder(query.getLeftArg(), bindings, dataset, converter, dialect, Collections.EMPTY_SET); - right = new SQLBuilder(query.getRightArg(), bindings, dataset, converter, dialect, Collections.EMPTY_SET); + left = new SQLBuilder(query.getLeftArg(), bindings, dataset, converter, dialect, leftProjected); + right = new SQLBuilder(query.getRightArg(), bindings, dataset, converter, dialect, rightProjected); // next we make sure that both subqueries share the same SQL variables so the SQL UNION succeeds by // adding NULL aliases for all variables present in one but not the other int c = 0; Map<String,SQLVariable> leftVars = new HashMap<>(); for(SQLVariable svl : left.getVariables().values()) { - leftVars.put(svl.getSparqlName(), svl); + if(leftProjected.size() == 0 || leftProjected.contains(svl.getSparqlName())) { + leftVars.put(svl.getSparqlName(), svl); + } } Map<String,SQLVariable> rightVars = new HashMap<>(); for(SQLVariable svr : right.getVariables().values()) { - rightVars.put(svr.getSparqlName(), svr); + if(rightProjected.size() == 0 || rightProjected.contains(svr.getSparqlName())) { + rightVars.put(svr.getSparqlName(), svr); + } } // we have to homogenize variable names in both subqueries and make sure they have the same number of columns Map<String,String> sparqlToSQL = new HashMap<>(); for(SQLVariable svl : left.getVariables().values()) { - if(sparqlToSQL.containsKey(svl.getSparqlName())) { - svl.setName(sparqlToSQL.get(svl.getSparqlName())); - } else { - svl.setName("U"+ (++c)); - sparqlToSQL.put(svl.getSparqlName(), svl.getName()); + if(leftProjected.size() == 0 || leftProjected.contains(svl.getSparqlName())) { + if (sparqlToSQL.containsKey(svl.getSparqlName())) { + svl.setName(sparqlToSQL.get(svl.getSparqlName())); + } else { + svl.setName("U" + (++c)); + sparqlToSQL.put(svl.getSparqlName(), svl.getName()); + } } } - for(SQLVariable svl : right.getVariables().values()) { - if(sparqlToSQL.containsKey(svl.getSparqlName())) { - svl.setName(sparqlToSQL.get(svl.getSparqlName())); - } else { - svl.setName("U"+ (++c)); - sparqlToSQL.put(svl.getSparqlName(), svl.getName()); + for(SQLVariable svr : right.getVariables().values()) { + if(rightProjected.size() == 0 || rightProjected.contains(svr.getSparqlName())) { + if (sparqlToSQL.containsKey(svr.getSparqlName())) { + svr.setName(sparqlToSQL.get(svr.getSparqlName())); + } else { + svr.setName("U" + (++c)); + sparqlToSQL.put(svr.getSparqlName(), svr.getName()); + } } } @@ -92,6 +106,10 @@ public class SQLUnion extends SQLAbstractSubquery { svr.getExpressions().add("NULL"); svr.setProjectionType(ProjectionType.NODE); right.getVariables().put(svl.getSparqlName(),svr); + + if(rightProjected.size() > 0) { + right.getProjectedVars().add(svl.getSparqlName()); + } } variables.add(svl); } @@ -102,6 +120,10 @@ public class SQLUnion extends SQLAbstractSubquery { svl.getExpressions().add("NULL"); svl.setProjectionType(ProjectionType.NODE); left.getVariables().put(svr.getSparqlName(),svl); + + if(leftProjected.size() > 0) { + left.getProjectedVars().add(svr.getSparqlName()); + } } variables.add(svr); } @@ -148,6 +170,18 @@ public class SQLUnion extends SQLAbstractSubquery { } + private Set<String> getProjectedVariables(TupleExpr expr) { + if(expr instanceof Projection) { + Projection projection = (Projection)expr; + Set<String> projectedVars = new HashSet<>(); + for (ProjectionElem elem : projection.getProjectionElemList().getElements()) { + projectedVars.add(elem.getSourceName()); + } + return projectedVars; + } else { + return Collections.EMPTY_SET; + } + } } http://git-wip-us.apache.org/repos/asf/marmotta/blob/fa8ef614/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java b/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java index b3b2e2e..a888658 100644 --- a/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java +++ b/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java @@ -345,6 +345,14 @@ public class KiWiSparqlJoinTest { } + // MARMOTTA-552 + @Test + @Ignore("test skipped because of wrong evaluation in Sesame") + public void testQuery36() throws Exception { + testQuery("query36.sparql"); + } + + // INSERT/UPDATE @Test public void testUpdate01() throws Exception { http://git-wip-us.apache.org/repos/asf/marmotta/blob/fa8ef614/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query36.sparql ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query36.sparql b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query36.sparql new file mode 100644 index 0000000..dba866e --- /dev/null +++ b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query36.sparql @@ -0,0 +1,33 @@ +# +# 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. +# + +# MARMOTTA-552 + +SELECT ?class (count(?s) AS ?count) + WHERE + { { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?class } + UNION + { SELECT ?s + WHERE + { ?s ?a ?b + FILTER NOT EXISTS {?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?class } + } + GROUP BY ?s + } + } + GROUP BY ?class \ No newline at end of file
