Repository: marmotta Updated Branches: refs/heads/develop f222bf4c5 -> 2cfd480ad
fix some bugs in special cases with BIND, UNION, GROUP BY and ORDER BY Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/2cfd480a Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/2cfd480a Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/2cfd480a Branch: refs/heads/develop Commit: 2cfd480add868814fb29ec3cd1c4501115b9b8f0 Parents: f222bf4 Author: Sebastian Schaffert <[email protected]> Authored: Thu Sep 18 12:06:43 2014 +0200 Committer: Sebastian Schaffert <[email protected]> Committed: Thu Sep 18 12:06:43 2014 +0200 ---------------------------------------------------------------------- .../kiwi/sparql/builder/ExtensionFinder.java | 15 ++++-- .../kiwi/sparql/builder/SQLBuilder.java | 53 +++++++++++++++----- .../kiwi/sparql/builder/SQLVariable.java | 14 ++++++ .../kiwi/sparql/test/KiWiSparqlJoinTest.java | 16 ++++++ .../marmotta/kiwi/sparql/test/query29.sparql | 26 ++++++++++ .../marmotta/kiwi/sparql/test/query30.sparql | 25 +++++++++ 6 files changed, 133 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/2cfd480a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ExtensionFinder.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ExtensionFinder.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ExtensionFinder.java index e1c8f4d..2012f16 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ExtensionFinder.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ExtensionFinder.java @@ -17,10 +17,7 @@ package org.apache.marmotta.kiwi.sparql.builder; -import org.openrdf.query.algebra.Extension; -import org.openrdf.query.algebra.ExtensionElem; -import org.openrdf.query.algebra.TupleExpr; -import org.openrdf.query.algebra.Var; +import org.openrdf.query.algebra.*; import org.openrdf.query.algebra.helpers.QueryModelVisitorBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,4 +51,14 @@ public class ExtensionFinder extends QueryModelVisitorBase<RuntimeException> { } super.meet(node); } + + @Override + public void meet(Projection node) throws RuntimeException { + // stop here, this is a subquery in SQL + } + + @Override + public void meet(Union node) throws RuntimeException { + // stop here, this is a subquery in SQL + } } http://git-wip-us.apache.org/repos/asf/marmotta/blob/2cfd480a/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 c90b6da..cca14a3 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 @@ -323,8 +323,11 @@ public class SQLBuilder { addVariable(sv); } + // TODO: ANY as OPType here is dangerous, because the OPType should depends on projection and actual use + // of variables in conditions etc if (hasNodeCondition(v.getName(), query)) { - sv.getAliases().add(evaluateExpression(ext.getExpr(), OPTypes.ANY)); + //sv.getAliases().add(evaluateExpression(ext.getExpr(), OPTypes.VALUE)); + sv.getBindings().add(ext.getExpr()); } sv.getExpressions().add(evaluateExpression(ext.getExpr(), OPTypes.ANY)); @@ -784,19 +787,45 @@ public class SQLBuilder { return "(" + var + ".ntype = 'string' OR " + var + ".ntype = 'int' OR " + var + ".ntype = 'double' OR " + var + ".ntype = 'date' OR " + var + ".ntype = 'boolean')"; } } else if(expr instanceof Var) { - String var = variables.get(((Var) expr).getName()).getPrimaryAlias(); + // distinguish between the case where the variable is plain and the variable is bound + SQLVariable sv = variables.get(((Var) expr).getName()); - if(optype == null) { - return var + ".svalue"; + if(sv.getBindings().size() > 0) { + // in case the variable is actually an alias for an expression, we evaluate that expression instead, effectively replacing the + // variable occurrence with its value + return evaluateExpression(sv.getBindings().get(0),optype); } else { - switch (optype) { - case STRING: return var + ".svalue"; - case INT: return var + ".ivalue"; - case DOUBLE: return var + ".dvalue"; - case DATE: return var + ".tvalue"; - case VALUE: return var + ".svalue"; - case URI: return var + ".svalue"; - case ANY: return var + ".id"; + String var = sv.getPrimaryAlias(); + + if(sv.getProjectionType() != ProjectionType.NODE && sv.getProjectionType() != ProjectionType.NONE) { + // in case the variable represents a constructed or bound value instead of a node, we need to + // use the SQL expression as value; SQL should take care of proper casting... + // TODO: explicit casting needed? + return sv.getExpressions().get(0); + } else { + // in case the variable represents an entry from the NODES table (i.e. has been bound to a node + // in the database, we take the NODES alias and resolve to the correct column according to the + // operator type + if (optype == null) { + return var + ".svalue"; + } else { + switch (optype) { + case STRING: + return var + ".svalue"; + case INT: + return var + ".ivalue"; + case DOUBLE: + return var + ".dvalue"; + case DATE: + return var + ".tvalue"; + case VALUE: + return var + ".svalue"; + case URI: + return var + ".svalue"; + case ANY: + return var + ".id"; + } + } } } } else if(expr instanceof ValueConstant) { http://git-wip-us.apache.org/repos/asf/marmotta/blob/2cfd480a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLVariable.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLVariable.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLVariable.java index a5dfb76..6fcd3d8 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLVariable.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLVariable.java @@ -17,6 +17,8 @@ package org.apache.marmotta.kiwi.sparql.builder; +import org.openrdf.query.algebra.ValueExpr; + import java.text.Collator; import java.util.ArrayList; import java.util.Comparator; @@ -54,6 +56,13 @@ public class SQLVariable { private List<String> expressions; /** + * A list of value expressions bound to this variable; this is needed in case the variable is used in a filter or + * ORDER BY, because then we need to determine the type. + */ + private List<ValueExpr> bindings; + + + /** * Set to something else than NONE when this variable is contained in the SELECT part of the query, i.e. needs to be projected. * Decides on how the variable will be projected (as node -> ID, as value -> string or numeric field) */ @@ -64,6 +73,7 @@ public class SQLVariable { this.sparqlName = sparqlName; this.aliases = new ArrayList<>(); + this.bindings = new ArrayList<>(); this.expressions = new ArrayList<>(); } @@ -87,6 +97,10 @@ public class SQLVariable { return aliases.get(0); } + public List<ValueExpr> getBindings() { + return bindings; + } + public List<String> getExpressions() { return expressions; } http://git-wip-us.apache.org/repos/asf/marmotta/blob/2cfd480a/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 1ac3343..c1149e2 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 @@ -297,6 +297,22 @@ public class KiWiSparqlJoinTest { } + // union with bind and order by + @Test + public void testQuery29() throws Exception { + testQuery("query29.sparql"); + } + + + + // bind with order by + @Test + public void testQuery30() throws Exception { + testQuery("query30.sparql"); + } + + + // INSERT/UPDATE @Test public void testUpdate01() throws Exception { http://git-wip-us.apache.org/repos/asf/marmotta/blob/2cfd480a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query29.sparql ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query29.sparql b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query29.sparql new file mode 100644 index 0000000..89eb239 --- /dev/null +++ b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query29.sparql @@ -0,0 +1,26 @@ +# +# 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. +# +PREFIX foaf: <http://xmlns.com/foaf/0.1/> + +SELECT ?p ?name ?likes ?fname ?isperson WHERE { + ?p foaf:name ?name . + { ?p foaf:knows ?likes . ?likes foaf:name ?fname bind(true as ?isperson) } + UNION + { ?p foaf:interest ?likes bind(false as ?isperson)} + +} ORDER BY ASC(?isperson) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/marmotta/blob/2cfd480a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query30.sparql ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query30.sparql b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query30.sparql new file mode 100644 index 0000000..c9b5743 --- /dev/null +++ b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query30.sparql @@ -0,0 +1,25 @@ +# +# 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. +# +PREFIX foaf: <http://xmlns.com/foaf/0.1/> + +SELECT ?p ?name ?likes WHERE { + ?p foaf:name ?name . + OPTIONAL { ?p foaf:knows ?knows } + OPTIONAL { ?p foaf:interest ?interest } + BIND (COALESCE(?knows,?interest) AS ?likes) +} ORDER BY ASC(?likes) \ No newline at end of file
