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/01/14 11:31:31 UTC
git commit: cleanups in SPARQL module
Updated Branches:
refs/heads/develop 967c1e239 -> 0aeedd8ab
cleanups in SPARQL module
Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/0aeedd8a
Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/0aeedd8a
Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/0aeedd8a
Branch: refs/heads/develop
Commit: 0aeedd8aba0d716343169621ae9151b3ce7a4b0f
Parents: 967c1e2
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Tue Jan 14 11:31:19 2014 +0100
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Tue Jan 14 11:31:19 2014 +0100
----------------------------------------------------------------------
.../kiwi/sparql/persistence/DistinctFinder.java | 47 ++++++
.../sparql/persistence/FilterCollector.java | 47 ++++++
.../persistence/KiWiSparqlConnection.java | 161 +-----------------
.../kiwi/sparql/persistence/LimitFinder.java | 44 +++++
.../kiwi/sparql/persistence/OPTypeFinder.java | 162 +++++++++++++++++++
.../kiwi/sparql/persistence/OPTypes.java | 27 ++++
.../sparql/persistence/PatternCollector.java | 46 ++++++
.../kiwi/test/junit/KiWiDatabaseRunner.java | 8 +-
8 files changed, 377 insertions(+), 165 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/DistinctFinder.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/DistinctFinder.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/DistinctFinder.java
new file mode 100644
index 0000000..987ba69
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/DistinctFinder.java
@@ -0,0 +1,47 @@
+/*
+ * 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.persistence;
+
+import org.openrdf.query.algebra.Distinct;
+import org.openrdf.query.algebra.Reduced;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
+
+/**
+* Find distinct/reduced in a tuple expression.
+*
+* @author Sebastian Schaffert (sschaffert@apache.org)
+*/
+class DistinctFinder extends QueryModelVisitorBase<RuntimeException> {
+
+ boolean distinct = false;
+
+ DistinctFinder(TupleExpr expr) {
+ expr.visit(this);
+ }
+
+ @Override
+ public void meet(Distinct node) throws RuntimeException {
+ distinct = true;
+ }
+
+ @Override
+ public void meet(Reduced node) throws RuntimeException {
+ distinct = true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/FilterCollector.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/FilterCollector.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/FilterCollector.java
new file mode 100644
index 0000000..dbf33e1
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/FilterCollector.java
@@ -0,0 +1,47 @@
+/*
+ * 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.persistence;
+
+import org.openrdf.query.algebra.Filter;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.ValueExpr;
+import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Collect all filter conditions in a query expression
+*
+* @author Sebastian Schaffert (sschaffert@apache.org)
+*/
+class FilterCollector extends QueryModelVisitorBase<RuntimeException> {
+
+ List<ValueExpr> filters = new ArrayList<>();
+
+ FilterCollector(TupleExpr expr) {
+ expr.visit(this);
+ }
+
+ @Override
+ public void meet(Filter node) throws RuntimeException {
+ filters.add(node.getCondition());
+
+ super.meet(node);
+ }
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/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 8b91ab4..9e23adb 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
@@ -23,7 +23,6 @@ import info.aduna.iteration.CloseableIteratorIteration;
import info.aduna.iteration.EmptyIteration;
import info.aduna.iteration.Iterations;
import org.apache.commons.lang3.StringUtils;
-import org.apache.marmotta.commons.sesame.model.Namespaces;
import org.apache.marmotta.commons.util.DateUtils;
import org.apache.marmotta.kiwi.model.rdf.KiWiNode;
import org.apache.marmotta.kiwi.persistence.KiWiConnection;
@@ -40,7 +39,6 @@ import org.openrdf.query.Binding;
import org.openrdf.query.BindingSet;
import org.openrdf.query.Dataset;
import org.openrdf.query.algebra.*;
-import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
import org.openrdf.query.impl.MapBindingSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -510,13 +508,13 @@ public class KiWiSparqlConnection {
} else if(expr instanceof Compare) {
Compare cmp = (Compare)expr;
- OPTypes ot = determineOpType(cmp.getLeftArg(), cmp.getRightArg());
+ OPTypes ot = new OPTypeFinder(cmp).coerce();
return evaluateExpression(cmp.getLeftArg(),queryVariables, ot) + getSQLOperator(cmp.getOperator()) + evaluateExpression(cmp.getRightArg(),queryVariables, ot);
} else if(expr instanceof MathExpr) {
MathExpr cmp = (MathExpr)expr;
- OPTypes ot = determineOpType(cmp.getLeftArg(), cmp.getRightArg());
+ OPTypes ot = new OPTypeFinder(cmp).coerce();
if(ot == OPTypes.STRING) {
if(cmp.getOperator() == MathExpr.MathOp.PLUS) {
@@ -742,88 +740,6 @@ public class KiWiSparqlConnection {
}
-
- private OPTypes determineOpType(ValueExpr expr) {
- if(expr instanceof ValueConstant) {
- if(((ValueConstant) expr).getValue() instanceof Literal) {
- Literal l = (Literal)((ValueConstant) expr).getValue();
- String type = l.getDatatype() != null ? l.getDatatype().stringValue() : null;
-
- if(StringUtils.equals(Namespaces.NS_XSD + "double", type)
- || StringUtils.equals(Namespaces.NS_XSD + "float", type)
- || StringUtils.equals(Namespaces.NS_XSD + "decimal", type)) {
- return OPTypes.DOUBLE;
- } else if(StringUtils.equals(Namespaces.NS_XSD + "integer", type)
- || StringUtils.equals(Namespaces.NS_XSD + "long", type)
- || StringUtils.equals(Namespaces.NS_XSD + "int", type)
- || StringUtils.equals(Namespaces.NS_XSD + "short", type)
- || StringUtils.equals(Namespaces.NS_XSD + "nonNegativeInteger", type)
- || StringUtils.equals(Namespaces.NS_XSD + "nonPositiveInteger", type)
- || StringUtils.equals(Namespaces.NS_XSD + "negativeInteger", type)
- || StringUtils.equals(Namespaces.NS_XSD + "positiveInteger", type)
- || StringUtils.equals(Namespaces.NS_XSD + "unsignedLong", type)
- || StringUtils.equals(Namespaces.NS_XSD + "unsignedShort", type)
- || StringUtils.equals(Namespaces.NS_XSD + "byte", type)
- || StringUtils.equals(Namespaces.NS_XSD + "unsignedByte", type)) {
- return OPTypes.INT;
- } else if(StringUtils.equals(Namespaces.NS_XSD + "dateTime", type)
- || StringUtils.equals(Namespaces.NS_XSD + "date", type)
- || StringUtils.equals(Namespaces.NS_XSD + "time", type)) {
- return OPTypes.DATE;
- } else {
- return OPTypes.STRING;
- }
- } else {
- return OPTypes.STRING;
- }
- } else if(expr instanceof Str) {
- return OPTypes.STRING;
- } else if(expr instanceof Lang) {
- return OPTypes.STRING;
- } else if(expr instanceof LocalName) {
- return OPTypes.STRING;
- } else if(expr instanceof Label) {
- return OPTypes.STRING;
- } else if(expr instanceof MathExpr) {
- return determineOpType(((MathExpr) expr).getLeftArg(), ((MathExpr) expr).getRightArg());
- } else if(expr instanceof Var) {
- return OPTypes.ANY;
- } else if(expr instanceof FunctionCall) {
- FunctionCall fc = (FunctionCall)expr;
- URI fnUri = new URIImpl(fc.getURI());
-
- String[] args = new String[fc.getArgs().size()];
-
- OPTypes fOpType = functionReturnTypes.get(fnUri);
- if(fOpType == null) {
- fOpType = OPTypes.ANY;
- }
- return fOpType;
- } else {
- throw new IllegalArgumentException("unsupported expression: "+expr);
- }
- }
-
- private OPTypes determineOpType(ValueExpr expr1, ValueExpr expr2) {
- OPTypes left = determineOpType(expr1);
- OPTypes right = determineOpType(expr2);
-
- if(left == OPTypes.ANY) {
- return right;
- } else if(right == OPTypes.ANY) {
- return left;
- } else if(left == right) {
- return left;
- } else if( (left == OPTypes.INT && right == OPTypes.DOUBLE) || (left == OPTypes.DOUBLE && right == OPTypes.INT)) {
- return OPTypes.DOUBLE;
- } else if( (left == OPTypes.STRING) || (right == OPTypes.STRING)) {
- return OPTypes.STRING;
- } else {
- throw new IllegalArgumentException("unsupported type coercion: " + left + " and " + right);
- }
- }
-
-
/**
* Test if the regular expression given in the pattern can be simplified to a LIKE SQL statement; these are
* considerably more efficient to evaluate in most databases, so in case we can simplify, we return a LIKE.
@@ -908,10 +824,6 @@ public class KiWiSparqlConnection {
}
- private static enum OPTypes {
- STRING, DOUBLE, INT, DATE, BOOL, ANY
- }
-
public KiWiDialect getDialect() {
return parent.getDialect();
}
@@ -960,73 +872,4 @@ public class KiWiSparqlConnection {
}
- private static class LimitFinder extends QueryModelVisitorBase<RuntimeException> {
-
- long limit = -1, offset = -1;
-
- private LimitFinder(TupleExpr expr) {
- expr.visit(this);
- }
-
- @Override
- public void meet(Slice node) throws RuntimeException {
- if(node.hasLimit())
- limit = node.getLimit();
- if(node.hasOffset())
- offset = node.getOffset();
- }
- }
-
- private static class DistinctFinder extends QueryModelVisitorBase<RuntimeException> {
-
- boolean distinct = false;
-
- private DistinctFinder(TupleExpr expr) {
- expr.visit(this);
- }
-
- @Override
- public void meet(Distinct node) throws RuntimeException {
- distinct = true;
- }
-
- @Override
- public void meet(Reduced node) throws RuntimeException {
- distinct = true;
- }
- }
-
-
- private static class PatternCollector extends QueryModelVisitorBase<RuntimeException> {
-
- List<StatementPattern> patterns = new ArrayList<>();
-
- private PatternCollector(TupleExpr expr) {
- expr.visit(this);
- }
-
- @Override
- public void meet(StatementPattern node) throws RuntimeException {
- patterns.add(node);
-
- super.meet(node);
- }
- }
-
-
- private static class FilterCollector extends QueryModelVisitorBase<RuntimeException> {
-
- List<ValueExpr> filters = new ArrayList<>();
-
- private FilterCollector(TupleExpr expr) {
- expr.visit(this);
- }
-
- @Override
- public void meet(Filter node) throws RuntimeException {
- filters.add(node.getCondition());
-
- super.meet(node);
- }
- }
}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/LimitFinder.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/LimitFinder.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/LimitFinder.java
new file mode 100644
index 0000000..f0547c6
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/LimitFinder.java
@@ -0,0 +1,44 @@
+/*
+ * 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.persistence;
+
+import org.openrdf.query.algebra.Slice;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
+
+/**
+* Find the offset and limit values in a tuple expression
+*
+* @author Sebastian Schaffert (sschaffert@apache.org)
+*/
+class LimitFinder extends QueryModelVisitorBase<RuntimeException> {
+
+ long limit = -1, offset = -1;
+
+ LimitFinder(TupleExpr expr) {
+ expr.visit(this);
+ }
+
+ @Override
+ public void meet(Slice node) throws RuntimeException {
+ if(node.hasLimit())
+ limit = node.getLimit();
+ if(node.hasOffset())
+ offset = node.getOffset();
+ }
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypeFinder.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypeFinder.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypeFinder.java
new file mode 100644
index 0000000..85312f0
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypeFinder.java
@@ -0,0 +1,162 @@
+/*
+ * 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.persistence;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.marmotta.commons.sesame.model.Namespaces;
+import org.openrdf.model.Literal;
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.model.vocabulary.FN;
+import org.openrdf.query.algebra.*;
+import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Determine the operand type of a value expression. Get the coerced value by calling coerce().
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class OPTypeFinder extends QueryModelVisitorBase<RuntimeException> {
+
+ List<OPTypes> optypes = new ArrayList<>();
+
+ private static Map<URI,OPTypes> functionReturnTypes = new HashMap<>();
+ static {
+ functionReturnTypes.put(FN.CONCAT, OPTypes.STRING);
+ functionReturnTypes.put(FN.CONTAINS, OPTypes.BOOL);
+ functionReturnTypes.put(FN.LOWER_CASE, OPTypes.STRING);
+ functionReturnTypes.put(FN.UPPER_CASE, OPTypes.STRING);
+ functionReturnTypes.put(FN.REPLACE, OPTypes.STRING);
+ functionReturnTypes.put(FN.SUBSTRING_AFTER, OPTypes.STRING);
+ functionReturnTypes.put(FN.SUBSTRING_BEFORE, OPTypes.STRING);
+ functionReturnTypes.put(FN.STARTS_WITH, OPTypes.BOOL);
+ functionReturnTypes.put(FN.ENDS_WITH, OPTypes.BOOL);
+ functionReturnTypes.put(FN.STRING_LENGTH, OPTypes.INT);
+ functionReturnTypes.put(FN.SUBSTRING, OPTypes.STRING);
+
+ functionReturnTypes.put(FN.NUMERIC_ABS, OPTypes.DOUBLE);
+ functionReturnTypes.put(FN.NUMERIC_CEIL, OPTypes.INT);
+ functionReturnTypes.put(FN.NUMERIC_FLOOR, OPTypes.INT);
+ functionReturnTypes.put(FN.NUMERIC_ROUND, OPTypes.INT);
+
+ }
+
+
+
+ public OPTypeFinder(ValueExpr expr) {
+ expr.visit(this);
+ }
+
+ @Override
+ public void meet(ValueConstant node) throws RuntimeException {
+ if(node.getValue() instanceof Literal) {
+ Literal l = (Literal)node.getValue();
+ String type = l.getDatatype() != null ? l.getDatatype().stringValue() : null;
+
+ if(StringUtils.equals(Namespaces.NS_XSD + "double", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "float", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "decimal", type)) {
+ optypes.add(OPTypes.DOUBLE);
+ } else if(StringUtils.equals(Namespaces.NS_XSD + "integer", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "long", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "int", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "short", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "nonNegativeInteger", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "nonPositiveInteger", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "negativeInteger", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "positiveInteger", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "unsignedLong", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "unsignedShort", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "byte", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "unsignedByte", type)) {
+ optypes.add(OPTypes.INT);
+ } else if(StringUtils.equals(Namespaces.NS_XSD + "dateTime", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "date", type)
+ || StringUtils.equals(Namespaces.NS_XSD + "time", type)) {
+ optypes.add(OPTypes.DATE);
+ } else {
+ optypes.add(OPTypes.STRING);
+ }
+ } else {
+ optypes.add(OPTypes.STRING);
+ }
+ }
+
+ @Override
+ public void meet(Str node) throws RuntimeException {
+ optypes.add(OPTypes.STRING);
+ }
+
+ @Override
+ public void meet(Lang node) throws RuntimeException {
+ optypes.add(OPTypes.STRING);
+ }
+
+ @Override
+ public void meet(LocalName node) throws RuntimeException {
+ optypes.add(OPTypes.STRING);
+ }
+
+ @Override
+ public void meet(Label node) throws RuntimeException {
+ optypes.add(OPTypes.STRING);
+ }
+
+
+ @Override
+ public void meet(FunctionCall fc) throws RuntimeException {
+ URI fnUri = new URIImpl(fc.getURI());
+
+ String[] args = new String[fc.getArgs().size()];
+
+ OPTypes fOpType = functionReturnTypes.get(fnUri);
+ if(fOpType == null) {
+ fOpType = OPTypes.ANY;
+ }
+ optypes.add(fOpType);
+ }
+
+
+ public OPTypes coerce() {
+ OPTypes left = OPTypes.ANY;
+
+ for(OPTypes right : optypes) {
+ if(left == OPTypes.ANY) {
+ left = right;
+ } else if(right == OPTypes.ANY) {
+ // keep left
+ } else if(left == right) {
+ // keep left
+ } else if( (left == OPTypes.INT && right == OPTypes.DOUBLE) || (left == OPTypes.DOUBLE && right == OPTypes.INT)) {
+ left = OPTypes.DOUBLE;
+ } else if( (left == OPTypes.STRING) || (right == OPTypes.STRING)) {
+ left = OPTypes.STRING;
+ } else {
+ throw new IllegalArgumentException("unsupported type coercion: " + left + " and " + right);
+ }
+ }
+ return left;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypes.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypes.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypes.java
new file mode 100644
index 0000000..f1ab84b
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/OPTypes.java
@@ -0,0 +1,27 @@
+/*
+ * 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.persistence;
+
+/**
+* Operand types for operations - used for implicit type coercion.
+*
+* @author Sebastian Schaffert (sschaffert@apache.org)
+*/
+enum OPTypes {
+ STRING, DOUBLE, INT, DATE, BOOL, ANY
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/PatternCollector.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/PatternCollector.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/PatternCollector.java
new file mode 100644
index 0000000..58331a4
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/persistence/PatternCollector.java
@@ -0,0 +1,46 @@
+/*
+ * 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.persistence;
+
+import org.openrdf.query.algebra.StatementPattern;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Collect all statement patterns in a tuple expression.
+*
+* @author Sebastian Schaffert (sschaffert@apache.org)
+*/
+class PatternCollector extends QueryModelVisitorBase<RuntimeException> {
+
+ List<StatementPattern> patterns = new ArrayList<>();
+
+ PatternCollector(TupleExpr expr) {
+ expr.visit(this);
+ }
+
+ @Override
+ public void meet(StatementPattern node) throws RuntimeException {
+ patterns.add(node);
+
+ super.meet(node);
+ }
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/0aeedd8a/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/junit/KiWiDatabaseRunner.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/junit/KiWiDatabaseRunner.java b/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/junit/KiWiDatabaseRunner.java
index 46d159d..25afcd9 100644
--- a/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/junit/KiWiDatabaseRunner.java
+++ b/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/junit/KiWiDatabaseRunner.java
@@ -38,11 +38,7 @@ import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
@@ -186,7 +182,7 @@ public class KiWiDatabaseRunner extends Suite {
checkDB = new CheckDBRule(config);
loggerRule = new ExecutionLogger();
}
-
+
@Override
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
final ForDialects forD = method.getAnnotation(ForDialects.class);