You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2014/09/18 12:06:29 UTC

git commit: fix some bugs in special cases with BIND, UNION, GROUP BY and ORDER BY

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 <ss...@apache.org>
Authored: Thu Sep 18 12:06:43 2014 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
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