You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by wi...@apache.org on 2014/09/18 07:38:16 UTC
[16/20] git commit: variable cleanups (proper description of variable
mappings between SPARQL and SQL)
variable cleanups (proper description of variable mappings between SPARQL and SQL)
Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/25568a16
Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/25568a16
Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/25568a16
Branch: refs/heads/ldp
Commit: 25568a16d4569256d79bbebc1603019773464d39
Parents: 64b504f
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Wed Sep 17 13:53:28 2014 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Wed Sep 17 13:53:28 2014 +0200
----------------------------------------------------------------------
.../kiwi/sparql/builder/FunctionDescriptor.java | 85 ------
.../kiwi/sparql/builder/ProjectionType.java | 2 +-
.../kiwi/sparql/builder/SQLBuilder.java | 275 ++++++++-----------
.../kiwi/sparql/builder/SQLFunction.java | 85 ++++++
.../kiwi/sparql/builder/SQLVariable.java | 48 +++-
.../persistence/KiWiSparqlConnection.java | 29 +-
6 files changed, 249 insertions(+), 275 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/marmotta/blob/25568a16/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/FunctionDescriptor.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/FunctionDescriptor.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/FunctionDescriptor.java
deleted file mode 100644
index 8f81019..0000000
--- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/FunctionDescriptor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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 org.apache.marmotta.kiwi.sparql.builder;
-
-import org.openrdf.model.URI;
-
-/**
- * Description of a SPARQL function to give details about various characteristics that we need when translating to
- * SQL, most importantly the parameter and return types.
- *
- * @author Sebastian Schaffert (sschaffert@apache.org)
- */
-public class FunctionDescriptor {
-
- public static enum Arity { ZERO, UNARY, BINARY, NARY };
-
- private URI uri;
-
- private OPTypes parameterType, returnType;
-
- private Arity arity;
-
- public FunctionDescriptor(URI uri, OPTypes parameterType, OPTypes returnType, Arity arity) {
- this.uri = uri;
- this.parameterType = parameterType;
- this.returnType = returnType;
- this.arity = arity;
- }
-
-
- public URI getUri() {
- return uri;
- }
-
- public OPTypes getParameterType() {
- return parameterType;
- }
-
- public OPTypes getReturnType() {
- return returnType;
- }
-
- public Arity getArity() {
- return arity;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- FunctionDescriptor that = (FunctionDescriptor) o;
-
- if (arity != that.arity) return false;
- if (parameterType != that.parameterType) return false;
- if (returnType != that.returnType) return false;
- if (!uri.equals(that.uri)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = uri.hashCode();
- result = 31 * result + parameterType.hashCode();
- result = 31 * result + returnType.hashCode();
- result = 31 * result + arity.hashCode();
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/25568a16/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ProjectionType.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ProjectionType.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ProjectionType.java
index 0c6c9fa..134b5c2 100644
--- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ProjectionType.java
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ProjectionType.java
@@ -23,5 +23,5 @@ package org.apache.marmotta.kiwi.sparql.builder;
* @author Sebastian Schaffert (sschaffert@apache.org)
*/
public enum ProjectionType {
- NODE, URI, STRING, INT, DOUBLE, DATE
+ NODE, URI, STRING, INT, DOUBLE, DATE, NONE
}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/25568a16/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 480cf0b..f2dc767 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
@@ -66,55 +66,55 @@ public class SQLBuilder {
/**
* Type coercion for function parameters and return values, defines for each function the type used by its parameters
*/
- private static Map<URI, FunctionDescriptor> functions = new HashMap<>();
+ private static Map<URI, SQLFunction> functions = new HashMap<>();
- private static void addFunction(URI uri, OPTypes paramType, OPTypes returnType, FunctionDescriptor.Arity arity) {
- functions.put(uri, new FunctionDescriptor(uri,paramType,returnType,arity));
+ private static void addFunction(URI uri, OPTypes paramType, OPTypes returnType, SQLFunction.Arity arity) {
+ functions.put(uri, new SQLFunction(uri,paramType,returnType,arity));
}
static {
- addFunction(FN.CONCAT, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.NARY);
- addFunction(FN.CONTAINS, OPTypes.STRING, OPTypes.BOOL, FunctionDescriptor.Arity.BINARY);
- addFunction(FN.LOWER_CASE, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
- addFunction(FN.UPPER_CASE, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
- addFunction(FN.REPLACE, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.BINARY);
- addFunction(FN.SUBSTRING_AFTER, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.BINARY);
- addFunction(FN.SUBSTRING_BEFORE, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.BINARY);
- addFunction(FN.STARTS_WITH, OPTypes.STRING, OPTypes.BOOL, FunctionDescriptor.Arity.BINARY);
- addFunction(FN.ENDS_WITH, OPTypes.STRING, OPTypes.BOOL, FunctionDescriptor.Arity.BINARY);
- addFunction(FN.STRING_LENGTH, OPTypes.STRING, OPTypes.INT, FunctionDescriptor.Arity.BINARY);
- addFunction(FN.SUBSTRING, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.BINARY);
-
- addFunction(FN.NUMERIC_ABS, OPTypes.DOUBLE, OPTypes.DOUBLE, FunctionDescriptor.Arity.UNARY);
- addFunction(FN.NUMERIC_CEIL, OPTypes.DOUBLE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN.NUMERIC_FLOOR, OPTypes.DOUBLE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN.NUMERIC_ROUND, OPTypes.DOUBLE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
-
-
- addFunction(FN_MARMOTTA.YEAR, OPTypes.DATE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.MONTH, OPTypes.DATE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.DAY, OPTypes.DATE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.HOURS, OPTypes.DATE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.MINUTES, OPTypes.DATE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.SECONDS, OPTypes.DATE, OPTypes.INT, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.TIMEZONE, OPTypes.DATE, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.TZ, OPTypes.DATE, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
-
- addFunction(FN_MARMOTTA.MD5, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.SHA1, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.SHA256, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.SHA384, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.SHA512, OPTypes.STRING, OPTypes.STRING, FunctionDescriptor.Arity.UNARY);
-
- addFunction(FN_MARMOTTA.UUID, OPTypes.ANY, OPTypes.URI, FunctionDescriptor.Arity.ZERO);
- addFunction(FN_MARMOTTA.STRUUID, OPTypes.ANY, OPTypes.STRING, FunctionDescriptor.Arity.ZERO);
- addFunction(FN_MARMOTTA.RAND, OPTypes.ANY, OPTypes.DOUBLE, FunctionDescriptor.Arity.ZERO);
-
- addFunction(FN_MARMOTTA.STDDEV, OPTypes.DOUBLE, OPTypes.DOUBLE, FunctionDescriptor.Arity.UNARY);
- addFunction(FN_MARMOTTA.VARIANCE, OPTypes.DOUBLE, OPTypes.DOUBLE, FunctionDescriptor.Arity.UNARY);
-
- addFunction(FN_MARMOTTA.QUERY_FULLTEXT, OPTypes.STRING, OPTypes.BOOL, FunctionDescriptor.Arity.NARY);
- addFunction(FN_MARMOTTA.SEARCH_FULLTEXT, OPTypes.STRING, OPTypes.BOOL, FunctionDescriptor.Arity.NARY);
+ addFunction(FN.CONCAT, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.NARY);
+ addFunction(FN.CONTAINS, OPTypes.STRING, OPTypes.BOOL, SQLFunction.Arity.BINARY);
+ addFunction(FN.LOWER_CASE, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.UNARY);
+ addFunction(FN.UPPER_CASE, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.UNARY);
+ addFunction(FN.REPLACE, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.BINARY);
+ addFunction(FN.SUBSTRING_AFTER, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.BINARY);
+ addFunction(FN.SUBSTRING_BEFORE, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.BINARY);
+ addFunction(FN.STARTS_WITH, OPTypes.STRING, OPTypes.BOOL, SQLFunction.Arity.BINARY);
+ addFunction(FN.ENDS_WITH, OPTypes.STRING, OPTypes.BOOL, SQLFunction.Arity.BINARY);
+ addFunction(FN.STRING_LENGTH, OPTypes.STRING, OPTypes.INT, SQLFunction.Arity.BINARY);
+ addFunction(FN.SUBSTRING, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.BINARY);
+
+ addFunction(FN.NUMERIC_ABS, OPTypes.DOUBLE, OPTypes.DOUBLE, SQLFunction.Arity.UNARY);
+ addFunction(FN.NUMERIC_CEIL, OPTypes.DOUBLE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN.NUMERIC_FLOOR, OPTypes.DOUBLE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN.NUMERIC_ROUND, OPTypes.DOUBLE, OPTypes.INT, SQLFunction.Arity.UNARY);
+
+
+ addFunction(FN_MARMOTTA.YEAR, OPTypes.DATE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.MONTH, OPTypes.DATE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.DAY, OPTypes.DATE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.HOURS, OPTypes.DATE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.MINUTES, OPTypes.DATE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.SECONDS, OPTypes.DATE, OPTypes.INT, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.TIMEZONE, OPTypes.DATE, OPTypes.STRING, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.TZ, OPTypes.DATE, OPTypes.STRING, SQLFunction.Arity.UNARY);
+
+ addFunction(FN_MARMOTTA.MD5, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.SHA1, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.SHA256, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.SHA384, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.SHA512, OPTypes.STRING, OPTypes.STRING, SQLFunction.Arity.UNARY);
+
+ addFunction(FN_MARMOTTA.UUID, OPTypes.ANY, OPTypes.URI, SQLFunction.Arity.ZERO);
+ addFunction(FN_MARMOTTA.STRUUID, OPTypes.ANY, OPTypes.STRING, SQLFunction.Arity.ZERO);
+ addFunction(FN_MARMOTTA.RAND, OPTypes.ANY, OPTypes.DOUBLE, SQLFunction.Arity.ZERO);
+
+ addFunction(FN_MARMOTTA.STDDEV, OPTypes.DOUBLE, OPTypes.DOUBLE, SQLFunction.Arity.UNARY);
+ addFunction(FN_MARMOTTA.VARIANCE, OPTypes.DOUBLE, OPTypes.DOUBLE, SQLFunction.Arity.UNARY);
+
+ addFunction(FN_MARMOTTA.QUERY_FULLTEXT, OPTypes.STRING, OPTypes.BOOL, SQLFunction.Arity.NARY);
+ addFunction(FN_MARMOTTA.SEARCH_FULLTEXT, OPTypes.STRING, OPTypes.BOOL, SQLFunction.Arity.NARY);
}
@@ -140,29 +140,15 @@ public class SQLBuilder {
private Set<String> groupLabels;
/**
- * A map for mapping the SPARQL variable names to internal names used for constructing SQL aliases.
- * Will look like { ?x -> "V1", ?y -> "V2", ... }
+ * Maintains a mapping between SPARQL variable names and internal variable descriptions. The internal description
+ * contains information whether the variable needs to be projected, what SQL expressions represent this variable,
+ * and what internal aliases to use.
*/
- private Map<Var,String> variableNames = new HashMap<>();
-
- /**
- * A map for mapping SPARQL variables to field names; each variable might have one or more field names,
- * depending on the number of patterns it occurs in; will look like
- * { ?x -> ["P1_V1", "P2_V1"], ?y -> ["P2_V2"], ... }
- */
- private Map<String,List<String>> queryVariables = new HashMap<>();
-
-
- /**
- * A map for mapping SPARQL variables to database node ID selectors. A node ID can occur either as
- * primary key in the NODES table or in the subject, predicate, object and context fields of a pattern.
- */
- private Map<Var,List<String>> queryVariableIds = new HashMap<>();
-
-
- private Map<Var, ProjectionType> variableTypes = new HashMap<>();
+ private Map<String,SQLVariable> variables = new HashMap<>();
+ private void addVariable(SQLVariable v) {
+ variables.put(v.getSparqlVariable().getName(),v);
+ }
- private Set<Var> projectedVariables = new HashSet<>();
/**
* The triple patterns collected from the query.
@@ -212,56 +198,9 @@ public class SQLBuilder {
prepareBuilder();
}
- public boolean isDistinct() {
- return distinct;
- }
-
- public void setDistinct(boolean distinct) {
- this.distinct = distinct;
- }
-
- public long getOffset() {
- return offset;
- }
-
- public void setOffset(long offset) {
- this.offset = offset;
- }
-
- public long getLimit() {
- return limit;
- }
-
- public void setLimit(long limit) {
- this.limit = limit;
- }
-
- /**
- * Return the set of variables projected by the SELECT clause
- * @return
- */
- public Set<Var> getProjectedVariables() {
- return projectedVariables;
- }
-
- /**
- * Return the SQL name of the SPARQL variable given as argument as generated by this query builder.
- * @param v
- * @return
- */
- public String getVariableName(Var v) {
- return variableNames.get(v);
- }
-
- /**
- * Return the type of a projected variable. Usually this is a node id to be resolved in the next step, but some
- * projections also create literal values of various types.
- * @param v
- * @return
- */
- public ProjectionType getVariableType(Var v) {
- return variableTypes.get(v);
+ public Map<String, SQLVariable> getVariables() {
+ return variables;
}
private void prepareBuilder() throws UnsatisfiableQueryException {
@@ -302,29 +241,32 @@ public class SQLBuilder {
for (int i = 0; i < fields.length; i++) {
if (fields[i] != null && !fields[i].hasValue()) {
Var v = fields[i];
- if (variableNames.get(v) == null) {
- variableNames.put(v, "V" + (++variableCount));
- variableTypes.put(v, ProjectionType.NODE);
- queryVariables.put(v.getName(), new LinkedList<String>());
- queryVariableIds.put(v, new LinkedList<String>());
+
+ SQLVariable sv = variables.get(v.getName());
+ if(!variables.containsKey(v.getName())) {
+ sv = new SQLVariable("V" + (++variableCount), v);
// select those variables that are really projected and not only needed in a grouping construct
if(new SQLProjectionFinder(query,v).found) {
- projectedVariables.add(v);
+ sv.setProjectionType(ProjectionType.NODE);
}
+
+ addVariable(sv);
}
+
String pName = p.getName();
- String vName = variableNames.get(v);
+ String vName = sv.getName();
+
if (hasNodeCondition(fields[i], query)) {
- queryVariables.get(v.getName()).add(pName + "_" + positions[i] + "_" + vName);
+ sv.getAliases().add(pName + "_" + positions[i] + "_" + vName);
}
// if the variable has been used before, add a join condition to the first occurrence
- if(queryVariableIds.get(v).size() > 0) {
- p.getConditions().add(queryVariableIds.get(v).get(0) + " = " + pName + "." + positions[i]);
+ if(sv.getExpressions().size() > 0) {
+ p.getConditions().add(sv.getExpressions().get(0) + " = " + pName + "." + positions[i]);
}
- queryVariableIds.get(v).add(pName + "." + positions[i]);
+ sv.getExpressions().add(pName + "." + positions[i]);
}
}
}
@@ -335,23 +277,23 @@ public class SQLBuilder {
// add all extensions to the variable list so they are properly considered in projections and clauses
for(ExtensionElem ext : extensions) {
Var v = new Var(ext.getName());
- if (variableNames.get(v) == null) {
- variableNames.put(v, "V" + (++variableCount));
- // set variable type according to expression; we need this later to decide what kind of node to construct
- variableTypes.put(v, getProjectionType(ext.getExpr()));
- queryVariables.put(v.getName(), new LinkedList<String>());
- queryVariableIds.put(v, new LinkedList<String>());
+ SQLVariable sv = variables.get(v.getName());
+ if(!variables.containsKey(v.getName())) {
+ sv = new SQLVariable("V" + (++variableCount), v);
// select those variables that are really projected and not only needed in a grouping construct
if(new SQLProjectionFinder(query,v).found) {
- projectedVariables.add(v);
+ sv.setProjectionType(getProjectionType(ext.getExpr()));
}
+
+ addVariable(sv);
}
+
if (hasNodeCondition(v, query)) {
- queryVariables.get(v.getName()).add(evaluateExpression(ext.getExpr(), OPTypes.ANY));
+ sv.getAliases().add(evaluateExpression(ext.getExpr(), OPTypes.ANY));
}
- queryVariableIds.get(v).add(evaluateExpression(ext.getExpr(), OPTypes.ANY));
+ sv.getExpressions().add(evaluateExpression(ext.getExpr(), OPTypes.ANY));
}
@@ -519,7 +461,7 @@ public class SQLBuilder {
for (SQLPattern p : f.getPatterns()) {
for(Map.Entry<SQLPattern.TripleColumns, Var> fieldEntry : p.getTripleFields().entrySet()) {
if(fieldEntry.getValue() != null && !fieldEntry.getValue().hasValue() && hasNodeCondition(fieldEntry.getValue(),query)) {
- p.setJoinField(fieldEntry.getKey(), variableNames.get(fieldEntry.getValue()));
+ p.setJoinField(fieldEntry.getKey(), variables.get(fieldEntry.getValue().getName()).getName());
}
}
}
@@ -530,17 +472,16 @@ public class SQLBuilder {
private String buildSelectClause() {
List<String> projections = new ArrayList<>();
- for(Iterator<Var> it = queryVariableIds.keySet().iterator(); it.hasNext(); ) {
- Var v = it.next();
- if(projectedVariables.contains(v)) {
- String projectedName = variableNames.get(v);
- String fromName = queryVariableIds.get(v).get(0);
+ for(SQLVariable v : variables.values()) {
+ if(v.getProjectionType() != ProjectionType.NONE) {
+ String projectedName = v.getName();
+ String fromName = v.getExpressions().get(0);
projections.add(fromName + " AS " + projectedName);
-
}
}
+
StringBuilder selectClause = new StringBuilder();
if(distinct) {
@@ -597,18 +538,18 @@ public class SQLBuilder {
// to the node given as binding
if(bindings != null) {
for(String v : bindings.getBindingNames()) {
- for(Map.Entry<Var,List<String>> entry : queryVariableIds.entrySet()) {
- if(entry.getKey().getName() != null && entry.getKey().getName().equals(v) &&
- entry.getValue() != null && entry.getValue().size() > 0) {
- List<String> vNames = entry.getValue();
- String vName = vNames.get(0);
- Value binding = converter.convert(bindings.getValue(v));
- if(binding instanceof KiWiNode) {
- whereConditions.add(vName+" = "+((KiWiNode)binding).getId());
- } else {
- throw new UnsatisfiableQueryException("the values in this binding have not been created by the KiWi value factory");
- }
+ SQLVariable sv = variables.get(v);
+
+ if(!sv.getExpressions().isEmpty()) {
+ List<String> vNames = sv.getExpressions();
+ String vName = vNames.get(0);
+ Value binding = converter.convert(bindings.getValue(v));
+ if(binding instanceof KiWiNode) {
+ whereConditions.add(vName+" = "+((KiWiNode)binding).getId());
+ } else {
+ throw new UnsatisfiableQueryException("the values in this binding have not been created by the KiWi value factory");
}
+
}
}
}
@@ -652,11 +593,10 @@ public class SQLBuilder {
if(groupLabels.size() > 0) {
groupClause.append("GROUP BY ");
for(Iterator<String> it = groupLabels.iterator(); it.hasNext(); ) {
- Var v = new Var(it.next());
-
+ SQLVariable sv = variables.get(it.next());
- if(queryVariableIds.get(v) != null) {
- Iterator<String> lit = queryVariableIds.get(v).iterator();
+ if(sv != null) {
+ Iterator<String> lit = sv.getExpressions().iterator();
while (lit.hasNext()) {
groupClause.append(lit.next());
if(lit.hasNext()) {
@@ -715,7 +655,7 @@ public class SQLBuilder {
Lang lang = (Lang)expr;
if(lang.getArg() instanceof Var) {
- return queryVariables.get(((Var) lang.getArg()).getName()).get(0) + ".lang";
+ return variables.get(((Var) lang.getArg()).getName()).getPrimaryAlias() + ".lang";
}
} else if(expr instanceof Compare) {
Compare cmp = (Compare)expr;
@@ -760,7 +700,7 @@ public class SQLBuilder {
if(arg instanceof ValueConstant) {
return Boolean.toString(((ValueConstant) arg).getValue() instanceof URI || ((ValueConstant) arg).getValue() instanceof BNode);
} else if(arg instanceof Var) {
- String var = queryVariables.get(((Var) arg).getName()).get(0);
+ String var = variables.get(((Var) arg).getName()).getPrimaryAlias();
return "(" + var + ".ntype = 'uri' OR " + var + ".ntype = 'bnode')";
}
@@ -771,7 +711,7 @@ public class SQLBuilder {
if(arg instanceof ValueConstant) {
return Boolean.toString(((ValueConstant) arg).getValue() instanceof URI);
} else if(arg instanceof Var) {
- String var = queryVariables.get(((Var) arg).getName()).get(0);
+ String var = variables.get(((Var) arg).getName()).getPrimaryAlias();
return var + ".ntype = 'uri'";
}
@@ -782,7 +722,7 @@ public class SQLBuilder {
if(arg instanceof ValueConstant) {
return Boolean.toString(((ValueConstant) arg).getValue() instanceof BNode);
} else if(arg instanceof Var) {
- String var = queryVariables.get(((Var) arg).getName()).get(0);
+ String var = variables.get(((Var) arg).getName()).getPrimaryAlias();
return var + ".ntype = 'bnode'";
}
@@ -793,12 +733,12 @@ public class SQLBuilder {
if(arg instanceof ValueConstant) {
return Boolean.toString(((ValueConstant) arg).getValue() instanceof Literal);
} else if(arg instanceof Var) {
- String var = queryVariables.get(((Var) arg).getName()).get(0);
+ String var = variables.get(((Var) arg).getName()).getPrimaryAlias();
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 = queryVariables.get(((Var) expr).getName()).get(0);
+ String var = variables.get(((Var) expr).getName()).getPrimaryAlias();
if(optype == null) {
return var + ".svalue";
@@ -851,9 +791,9 @@ public class SQLBuilder {
// so instead we construct an ARRAY of the bindings of all variables
List<String> countVariables = new ArrayList<>();
- for(Map.Entry<Var,List<String>> v : queryVariableIds.entrySet()) {
- if(!projectedVariables.contains(v.getKey())) {
- countVariables.add(v.getValue().get(0));
+ for(SQLVariable v : variables.values()) {
+ if(v.getProjectionType() == ProjectionType.NONE) {
+ countVariables.add(v.getExpressions().get(0));
}
}
countExp.append("ARRAY[");
@@ -1171,8 +1111,7 @@ public class SQLBuilder {
log.debug("original SPARQL syntax tree:\n {}", query);
log.debug("constructed SQL query string:\n {}",queryString);
- log.debug("SPARQL -> SQL node variable mappings:\n {}", queryVariables);
- log.debug("SPARQL -> SQL ID variable mappings:\n {}", queryVariableIds);
+ log.debug("SPARQL -> SQL node variable mappings:\n {}", variables);
return queryString;
}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/25568a16/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFunction.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFunction.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFunction.java
new file mode 100644
index 0000000..527da72
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFunction.java
@@ -0,0 +1,85 @@
+/*
+ * 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 org.apache.marmotta.kiwi.sparql.builder;
+
+import org.openrdf.model.URI;
+
+/**
+ * Description of a SPARQL function to give details about various characteristics that we need when translating to
+ * SQL, most importantly the parameter and return types.
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class SQLFunction {
+
+ public static enum Arity { ZERO, UNARY, BINARY, NARY };
+
+ private URI uri;
+
+ private OPTypes parameterType, returnType;
+
+ private Arity arity;
+
+ public SQLFunction(URI uri, OPTypes parameterType, OPTypes returnType, Arity arity) {
+ this.uri = uri;
+ this.parameterType = parameterType;
+ this.returnType = returnType;
+ this.arity = arity;
+ }
+
+
+ public URI getUri() {
+ return uri;
+ }
+
+ public OPTypes getParameterType() {
+ return parameterType;
+ }
+
+ public OPTypes getReturnType() {
+ return returnType;
+ }
+
+ public Arity getArity() {
+ return arity;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ SQLFunction that = (SQLFunction) o;
+
+ if (arity != that.arity) return false;
+ if (parameterType != that.parameterType) return false;
+ if (returnType != that.returnType) return false;
+ if (!uri.equals(that.uri)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = uri.hashCode();
+ result = 31 * result + parameterType.hashCode();
+ result = 31 * result + returnType.hashCode();
+ result = 31 * result + arity.hashCode();
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/25568a16/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 436558b..0950796 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
@@ -23,7 +23,8 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Representation of a SPARQL variable in SQL.
+ * Representation of a SPARQL variable in SQL. A SPARQL variable will always be translated into a column alias
+ * for either a subject/predicate/object/context field of a triple or a more complex expression (e.g. function evaluation).
*
* @author Sebastian Schaffert (sschaffert@apache.org)
*/
@@ -46,18 +47,24 @@ public class SQLVariable {
/**
- * A map for mapping SPARQL variables to database node ID selectors. A node ID can occur either as
- * primary key in the NODES table or in the subject, predicate, object and context fields of a pattern.
+ * A map for mapping SPARQL variables to database expressions (e.g. node ID selectors). A node ID can occur either as
+ * primary key in the NODES table or in the subject, predicate, object and context fields of a pattern. An expression
+ * can be e.g. a function evaluation.
*/
- private List<String> nodeIds;
+ private List<String> expressions;
+ /**
+ * 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)
+ */
+ private ProjectionType projectionType = ProjectionType.NONE;
public SQLVariable(String name, Var sparqlVariable) {
this.name = name;
this.sparqlVariable = sparqlVariable;
this.aliases = new ArrayList<>();
- this.nodeIds = new ArrayList<>();
+ this.expressions = new ArrayList<>();
}
public String getName() {
@@ -72,7 +79,34 @@ public class SQLVariable {
return aliases;
}
- public List<String> getNodeIds() {
- return nodeIds;
+ /**
+ * Primary alias for a variable, used e.g. when projecting or evaluating in functions. All others are added with join conditions.
+ * @return
+ */
+ public String getPrimaryAlias() {
+ return aliases.get(0);
+ }
+
+ public List<String> getExpressions() {
+ return expressions;
+ }
+
+ public ProjectionType getProjectionType() {
+ return projectionType;
+ }
+
+ public void setProjectionType(ProjectionType projectionType) {
+ this.projectionType = projectionType;
+ }
+
+ @Override
+ public String toString() {
+ return "Variable{" +
+ "SQL name='" + name + '\'' +
+ ", SPARQL name=" + sparqlVariable.getName() +
+ ", aliases=" + aliases +
+ ", expressions=" + expressions +
+ ", projectionType=" + projectionType +
+ '}';
}
}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/25568a16/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/KiWiSparqlConnection.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/KiWiSparqlConnection.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/KiWiSparqlConnection.java
index a662e40..1bd008c 100644
--- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/KiWiSparqlConnection.java
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/KiWiSparqlConnection.java
@@ -30,6 +30,7 @@ import org.apache.marmotta.kiwi.persistence.util.ResultTransformerFunction;
import org.apache.marmotta.kiwi.sail.KiWiValueFactory;
import org.apache.marmotta.kiwi.sparql.builder.ProjectionType;
import org.apache.marmotta.kiwi.sparql.builder.SQLBuilder;
+import org.apache.marmotta.kiwi.sparql.builder.SQLVariable;
import org.apache.marmotta.kiwi.sparql.exception.UnsatisfiableQueryException;
import org.openrdf.model.impl.LiteralImpl;
import org.openrdf.model.impl.URIImpl;
@@ -37,7 +38,6 @@ import org.openrdf.query.Binding;
import org.openrdf.query.BindingSet;
import org.openrdf.query.Dataset;
import org.openrdf.query.algebra.TupleExpr;
-import org.openrdf.query.algebra.Var;
import org.openrdf.query.impl.MapBindingSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -118,40 +118,41 @@ public class KiWiSparqlConnection {
public BindingSet apply(ResultSet row) throws SQLException {
MapBindingSet resultRow = new MapBindingSet();
- List<Var> vars = new ArrayList<>(builder.getProjectedVariables());
+ List<SQLVariable> vars = new ArrayList<>(builder.getVariables().values());
long[] nodeIds = new long[vars.size()];
for(int i=0; i<vars.size(); i++) {
- if(builder.getVariableType(vars.get(i)) == ProjectionType.NODE) {
- nodeIds[i] = row.getLong(builder.getVariableName(vars.get(i)));
+ SQLVariable sv = vars.get(i);
+ if(sv.getProjectionType() == ProjectionType.NODE) {
+ nodeIds[i] = row.getLong(sv.getName());
}
}
KiWiNode[] nodes = parent.loadNodesByIds(nodeIds);
for (int i = 0; i < vars.size(); i++) {
- Var v = vars.get(i);
+ SQLVariable sv = vars.get(i);
if(nodes[i] != null) {
// resolved node
- resultRow.addBinding(v.getName(), nodes[i]);
- } else {
+ resultRow.addBinding(sv.getSparqlVariable().getName(), nodes[i]);
+ } else if(sv.getProjectionType() != ProjectionType.NONE) {
// literal value
- String value = row.getString(builder.getVariableName(v));
+ String value = row.getString(sv.getName());
if(value != null) {
- switch (builder.getVariableType(v)) {
+ switch (sv.getProjectionType()) {
case URI:
- resultRow.addBinding(v.getName(), new URIImpl(value));
+ resultRow.addBinding(sv.getSparqlVariable().getName(), new URIImpl(value));
break;
case INT:
- resultRow.addBinding(v.getName(), new LiteralImpl(value, XSD.Integer));
+ resultRow.addBinding(sv.getSparqlVariable().getName(), new LiteralImpl(value, XSD.Integer));
break;
case DOUBLE:
- resultRow.addBinding(v.getName(), new LiteralImpl(value, XSD.Double));
+ resultRow.addBinding(sv.getSparqlVariable().getName(), new LiteralImpl(value, XSD.Double));
break;
case STRING:
- resultRow.addBinding(v.getName(), new LiteralImpl(value));
+ resultRow.addBinding(sv.getSparqlVariable().getName(), new LiteralImpl(value));
break;
default:
- resultRow.addBinding(v.getName(), new LiteralImpl(value));
+ resultRow.addBinding(sv.getSparqlVariable().getName(), new LiteralImpl(value));
break;
}
}