Updated Branches:
  refs/heads/develop a8d1abea1 -> 8f79ef1a8

SPARQL optimizations for FILTER


Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/8f79ef1a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/8f79ef1a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/8f79ef1a

Branch: refs/heads/develop
Commit: 8f79ef1a8d224141149704b7fd93e5747dc4ace1
Parents: a8d1abe
Author: Sebastian Schaffert <[email protected]>
Authored: Mon Apr 29 16:41:18 2013 +0200
Committer: Sebastian Schaffert <[email protected]>
Committed: Mon Apr 29 16:41:18 2013 +0200

----------------------------------------------------------------------
 .../evaluation/KiWiEvaluationStrategyImpl.java     |   72 ++++-
 .../sparql/persistence/KiWiSparqlConnection.java   |  236 ++++++++++++++-
 .../kiwi/sparql/sail/KiWiSparqlSailConnection.java |    6 +
 .../kiwi/sparql/test/KiWiSparqlJoinTest.java       |   22 ++
 .../marmotta/kiwi/sparql/test/demo-data.foaf       |   13 +-
 .../apache/marmotta/kiwi/sparql/test/query3.sparql |    7 +
 .../apache/marmotta/kiwi/sparql/test/query4.sparql |    7 +
 .../apache/marmotta/kiwi/sparql/test/query5.sparql |    8 +
 .../apache/marmotta/kiwi/sparql/test/query6.sparql |    8 +
 .../marmotta/kiwi/persistence/KiWiConnection.java  |    8 +-
 .../marmotta/kiwi/persistence/KiWiDialect.java     |   20 ++
 .../marmotta/kiwi/persistence/h2/H2Dialect.java    |   11 +
 .../kiwi/persistence/mysql/MySQLDialect.java       |   10 +
 .../kiwi/persistence/pgsql/PostgreSQLDialect.java  |   10 +
 .../marmotta/kiwi/sail/KiWiValueFactory.java       |    2 +-
 parent/pom.xml                                     |    5 +
 platform/marmotta-sparql/pom.xml                   |    4 +
 .../sparql/services/sail/SPARQLSailProvider.java   |   78 +++++
 .../src/main/resources/config-defaults.properties  |   28 --
 .../main/resources/config-descriptions.properties  |   32 +--
 20 files changed, 504 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/evaluation/KiWiEvaluationStrategyImpl.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/evaluation/KiWiEvaluationStrategyImpl.java
 
b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/evaluation/KiWiEvaluationStrategyImpl.java
index 713ff44..5e2fda0 100644
--- 
a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/evaluation/KiWiEvaluationStrategyImpl.java
+++ 
b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/evaluation/KiWiEvaluationStrategyImpl.java
@@ -23,9 +23,7 @@ import 
org.apache.marmotta.kiwi.sparql.persistence.KiWiSparqlConnection;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.Dataset;
 import org.openrdf.query.QueryEvaluationException;
-import org.openrdf.query.algebra.Join;
-import org.openrdf.query.algebra.StatementPattern;
-import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.*;
 import org.openrdf.query.algebra.evaluation.TripleSource;
 import org.openrdf.query.algebra.evaluation.impl.EvaluationStrategyImpl;
 import org.slf4j.Logger;
@@ -59,7 +57,7 @@ public class KiWiEvaluationStrategyImpl extends 
EvaluationStrategyImpl{
 
     @Override
     public CloseableIteration<BindingSet, QueryEvaluationException> 
evaluate(Join join, BindingSet bindings) throws QueryEvaluationException {
-        if(isPatternJoin(join)) {
+        if(isSupported(join)) {
             log.debug("applying KiWi JOIN optimizations on SPARQL query ...");
 
             try {
@@ -79,18 +77,80 @@ public class KiWiEvaluationStrategyImpl extends 
EvaluationStrategyImpl{
         }
     }
 
+    @Override
+    public CloseableIteration<BindingSet, QueryEvaluationException> 
evaluate(Filter join, BindingSet bindings) throws QueryEvaluationException {
+        if(isSupported(join)) {
+            log.debug("applying KiWi JOIN optimizations on SPARQL query ...");
+
+            try {
+                return new ExceptionConvertingIteration<BindingSet, 
QueryEvaluationException>(connection.evaluateJoin(join, bindings)) {
+                    @Override
+                    protected QueryEvaluationException convert(Exception e) {
+                        return new QueryEvaluationException(e);
+                    }
+                };
+            } catch (SQLException e) {
+                throw new QueryEvaluationException(e);
+            } catch (IllegalArgumentException e) {
+                throw new QueryEvaluationException(e);
+            }
+        } else {
+            return super.evaluate(join, bindings);
+        }
+    }
+
+
     /**
      * Test if a join consists only of joins of statement patterns; in this 
case we can apply a specific optimization.
      * @param expr
      * @return
      */
-    private static boolean isPatternJoin(TupleExpr expr) {
+    private static boolean isSupported(TupleExpr expr) {
         if(expr instanceof Join) {
-            return isPatternJoin(((Join) expr).getLeftArg()) && 
isPatternJoin(((Join) expr).getRightArg());
+            return isSupported(((Join) expr).getLeftArg()) && 
isSupported(((Join) expr).getRightArg());
+        } else if(expr instanceof Filter) {
+            return isSupported(((Filter) expr).getArg()) && 
isSupported(((Filter) expr).getCondition());
         } else if(expr instanceof StatementPattern) {
             return true;
         } else {
             return false;
         }
     }
+
+
+    private static boolean isSupported(ValueExpr expr) {
+        if(expr instanceof Compare) {
+            return isSupported(((Compare) expr).getLeftArg()) && 
isSupported(((Compare) expr).getRightArg());
+        } else if(expr instanceof MathExpr) {
+                return isSupported(((MathExpr) expr).getLeftArg()) && 
isSupported(((MathExpr) expr).getRightArg());
+        } else if(expr instanceof And) {
+            return isSupported(((And) expr).getLeftArg()) && 
isSupported(((And) expr).getRightArg());
+        } else if(expr instanceof Or) {
+            return isSupported(((Or) expr).getLeftArg()) && isSupported(((Or) 
expr).getRightArg());
+        } else if(expr instanceof ValueConstant) {
+            return true;
+        } else if(expr instanceof Var) {
+            return true;
+        } else if(expr instanceof Str) {
+            return isAtomic(((Str) expr).getArg());
+        } else if(expr instanceof Lang) {
+            return isAtomic(((Lang) expr).getArg());
+        } else if(expr instanceof LangMatches) {
+            return isSupported(((LangMatches) expr).getLeftArg()) && 
isConstant(((LangMatches) expr).getRightArg());
+        } else if(expr instanceof Regex) {
+            return isSupported(((Regex) expr).getArg()) && isAtomic(((Regex) 
expr).getPatternArg()) && ((Regex) expr).getFlagsArg() == null;
+        } else {
+            return false;
+        }
+    }
+
+
+    private static boolean isAtomic(ValueExpr expr) {
+        return expr instanceof Var || expr instanceof ValueConstant;
+    }
+
+    private static boolean isConstant(ValueExpr expr) {
+        return expr instanceof ValueConstant;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/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 92bbcb6..6a8566c 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
@@ -19,21 +19,19 @@ package org.apache.marmotta.kiwi.sparql.persistence;
 
 import com.google.common.base.Preconditions;
 import info.aduna.iteration.CloseableIteration;
-import org.apache.marmotta.kiwi.caching.KiWiCacheManager;
+import org.apache.commons.lang.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;
-import org.apache.marmotta.kiwi.persistence.KiWiDialect;
-import org.apache.marmotta.kiwi.persistence.KiWiPersistence;
 import org.apache.marmotta.kiwi.persistence.util.ResultSetIteration;
 import org.apache.marmotta.kiwi.persistence.util.ResultTransformerFunction;
 import org.apache.marmotta.kiwi.sail.KiWiValueFactory;
+import org.openrdf.model.Literal;
 import org.openrdf.model.Value;
 import org.openrdf.query.Binding;
 import org.openrdf.query.BindingSet;
-import org.openrdf.query.algebra.Join;
-import org.openrdf.query.algebra.StatementPattern;
-import org.openrdf.query.algebra.TupleExpr;
-import org.openrdf.query.algebra.Var;
+import org.openrdf.query.algebra.*;
 import org.openrdf.query.impl.MapBindingSet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,6 +39,8 @@ import org.slf4j.LoggerFactory;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.*;
 
 /**
@@ -55,6 +55,8 @@ public class KiWiSparqlConnection {
 
     private static Logger log = 
LoggerFactory.getLogger(KiWiSparqlConnection.class);
 
+    private static DateFormat sqlDateFormat = new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ss.S");
+
     private KiWiConnection parent;
     private KiWiValueFactory valueFactory;
 
@@ -69,9 +71,8 @@ public class KiWiSparqlConnection {
      * @param join
      * @return
      */
-    public CloseableIteration<BindingSet, SQLException> evaluateJoin(Join 
join, final BindingSet bindings) throws SQLException {
-        Preconditions.checkArgument(join.getLeftArg() instanceof 
StatementPattern || join.getLeftArg() instanceof Join);
-        Preconditions.checkArgument(join.getRightArg() instanceof 
StatementPattern || join.getRightArg() instanceof Join);
+    public CloseableIteration<BindingSet, SQLException> evaluateJoin(TupleExpr 
join, final BindingSet bindings) throws SQLException {
+        Preconditions.checkArgument(join instanceof Join || join instanceof 
Filter || join instanceof StatementPattern);
 
         // some definitions
         String[] positions = new String[] 
{"subject","predicate","object","context"};
@@ -234,7 +235,7 @@ public class KiWiSparqlConnection {
                 for(Map.Entry<Var,List<String>> entry : 
queryVariables.entrySet()) {
                     if(entry.getKey().getName() != null && 
entry.getKey().getName().equals(v) &&
                             entry.getValue() != null && 
entry.getValue().size() > 0) {
-                        List<String> vNames = queryVariables.get(v);
+                        List<String> vNames = entry.getValue();
                         String vName = vNames.get(0);
                         Value binding = 
valueFactory.convert(bindings.getValue(v));
                         if(binding instanceof KiWiNode) {
@@ -253,6 +254,15 @@ public class KiWiSparqlConnection {
             whereConditions.add(pName+".deleted = false");
         }
 
+
+        // 5. for each filter condition, add a statement to the where clause
+        List<ValueExpr> filters = new ArrayList<ValueExpr>();
+        collectFilters(join, filters);
+        for(ValueExpr expr : filters) {
+            whereConditions.add(evaluateExpression(expr,queryVariables, null));
+        }
+
+
         // construct the where clause
         StringBuilder whereClause = new StringBuilder();
         for(Iterator<String> it = whereConditions.iterator(); it.hasNext(); ) {
@@ -270,7 +280,9 @@ public class KiWiSparqlConnection {
                         "FROM " + fromClause + "\n " +
                         "WHERE " + whereClause;
 
-        log.debug("constructed SQL query string {}",queryString);
+        log.debug("original SPARQL syntax tree:\n {}", join);
+        log.debug("constructed SQL query string:\n {}",queryString);
+        log.debug("SPARQL -> SQL variable mappings:\n {}", queryVariables);
 
         PreparedStatement queryStatement = 
parent.getJDBCConnection().prepareStatement(queryString);
         ResultSet result = queryStatement.executeQuery();
@@ -296,6 +308,84 @@ public class KiWiSparqlConnection {
 
     }
 
+    private String evaluateExpression(ValueExpr expr, Map<Var, List<String>> 
queryVariables, OPTypes optype) {
+        if(expr instanceof And) {
+            return "(" + evaluateExpression(((And) expr).getLeftArg(), 
queryVariables, optype) + " AND " + evaluateExpression(((And) 
expr).getRightArg(),queryVariables, optype) + ")";
+        } else if(expr instanceof Or) {
+            return "(" + evaluateExpression(((Or) expr).getLeftArg(), 
queryVariables, optype) + " OR " + evaluateExpression(((Or) 
expr).getRightArg(),queryVariables, optype) + ")";
+        } else if(expr instanceof Str) {
+            Str str = (Str)expr;
+            // get value of argument and express it as string
+            if(str.getArg() instanceof Var) {
+                return queryVariables.get(str.getArg()).get(0) + ".svalue";
+            } else if(str.getArg() instanceof ValueConstant) {
+                return "'" + ((ValueConstant) 
str.getArg()).getValue().stringValue() + "'";
+            }
+        } else if(expr instanceof Lang) {
+            Lang lang = (Lang)expr;
+
+            if(lang.getArg() instanceof Var) {
+                return queryVariables.get(lang.getArg()).get(0) + ".lang";
+            }
+        } else if(expr instanceof Compare) {
+            Compare cmp = (Compare)expr;
+
+            OPTypes ot = determineOpType(cmp.getLeftArg(), cmp.getRightArg());
+
+            return evaluateExpression(cmp.getLeftArg(),queryVariables, ot) + 
getSQLOperator(cmp.getOperator()) + 
evaluateExpression(cmp.getRightArg(),queryVariables, ot);
+        } else if(expr instanceof Regex) {
+            Regex re = (Regex)expr;
+
+            // TODO: simplify the trivial cases to LIKE
+
+            return 
parent.getDialect().getRegexp(evaluateExpression(re.getArg(),queryVariables, 
optype), evaluateExpression(re.getPatternArg(), queryVariables, 
OPTypes.STRING));
+        } else if(expr instanceof LangMatches) {
+            LangMatches lm = (LangMatches)expr;
+            String value = evaluateExpression(lm.getLeftArg(), queryVariables, 
optype);
+            ValueConstant pattern = (ValueConstant) lm.getRightArg();
+
+            if(pattern.getValue().stringValue().equals("*")) {
+                return value + " LIKE '%'";
+            } else if(pattern.getValue().stringValue().equals("")) {
+                return value + " IS NULL";
+            } else {
+                return "(" + value + " = 
'"+pattern.getValue().stringValue()+"' OR " + 
parent.getDialect().getILike(value, "'" + pattern.getValue().stringValue() + 
"-%' )");
+            }
+        } else if(expr instanceof Var) {
+            String var = queryVariables.get(expr).get(0);
+
+            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";
+                    default: throw new IllegalArgumentException("unsupported 
value type: " + optype);
+                }
+            }
+        } else if(expr instanceof ValueConstant) {
+            String val = ((ValueConstant) expr).getValue().stringValue();
+
+            if(optype == null) {
+                return "'" + val + "'";
+            } else {
+                switch (optype) {
+                    case STRING: return "'" + val + "'";
+                    case INT:    return ""+Integer.parseInt(val);
+                    case DOUBLE: return ""+Double.parseDouble(val);
+                    case DATE:   return "'" + DateUtils.parseDate(val) + "'";
+                    default: throw new IllegalArgumentException("unsupported 
value type: " + optype);
+                }
+            }
+        }
+
+
+        throw new IllegalArgumentException("unsupported value expression: 
"+expr);
+    }
+
+
     /**
      * Collect all statement patterns in a tuple expression in depth-first 
order. The tuple expression may only
      * contain Join or StatementPattern expressions, otherwise an 
IllegalArgumentException is thrown.
@@ -306,6 +396,8 @@ public class KiWiSparqlConnection {
         if(expr instanceof Join) {
             collectPatterns(((Join) expr).getLeftArg(), patterns);
             collectPatterns(((Join) expr).getRightArg(), patterns);
+        } else if(expr instanceof Filter) {
+            collectPatterns(((Filter) expr).getArg(), patterns);
         } else if(expr instanceof StatementPattern) {
             patterns.add((StatementPattern)expr);
         } else {
@@ -313,4 +405,124 @@ public class KiWiSparqlConnection {
         }
 
     }
+
+
+    /**
+     * Collect all filter conditions in a tuple expression in depth-first 
order. The tuple expression may only
+     * contain Join or StatementPattern expressions, otherwise an 
IllegalArgumentException is thrown.
+     * @param expr
+     * @param filters
+     */
+    private void collectFilters(TupleExpr expr, List<ValueExpr> filters) {
+        if(expr instanceof Join) {
+            collectFilters(((Join) expr).getLeftArg(), filters);
+            collectFilters(((Join) expr).getRightArg(), filters);
+        } else if(expr instanceof Filter) {
+            filters.add(((Filter) expr).getCondition());
+        } else if(expr instanceof StatementPattern) {
+            // do nothing
+        } else {
+            throw new IllegalArgumentException("the tuple expression was 
neither a join nor a statement pattern: "+expr);
+        }
+
+    }
+
+
+    private String getSQLOperator(Compare.CompareOp op) {
+        switch (op) {
+            case EQ: return " = ";
+            case GE: return " >= ";
+            case GT: return " > ";
+            case LE: return " <= ";
+            case LT: return " < ";
+            case NE: return " <> ";
+        }
+        throw new IllegalArgumentException("unsupported operator type for 
comparison: "+op);
+    }
+
+
+    private String getSQLOperator(MathExpr.MathOp op) {
+        switch (op) {
+            case PLUS: return " + ";
+            case MINUS: return " - ";
+            case DIVIDE: return " / ";
+            case MULTIPLY: return " / ";
+        }
+        throw new IllegalArgumentException("unsupported operator type for math 
expression: "+op);
+    }
+
+
+
+    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().stringValue();
+
+                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 {
+            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);
+        }
+    }
+
+    private static enum OPTypes {
+        STRING, DOUBLE, INT, DATE, ANY
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSailConnection.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSailConnection.java
 
b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSailConnection.java
index d1a798f..bad56e3 100644
--- 
a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSailConnection.java
+++ 
b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSailConnection.java
@@ -36,6 +36,8 @@ import org.openrdf.sail.NotifyingSailConnection;
 import org.openrdf.sail.SailConnection;
 import org.openrdf.sail.SailException;
 import org.openrdf.sail.helpers.NotifyingSailConnectionWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Add file description here!
@@ -44,6 +46,8 @@ import 
org.openrdf.sail.helpers.NotifyingSailConnectionWrapper;
  */
 public class KiWiSparqlSailConnection extends NotifyingSailConnectionWrapper {
 
+    private static Logger log = 
LoggerFactory.getLogger(KiWiSparqlSailConnection.class);
+
     private KiWiSparqlConnection connection;
     private KiWiValueFactory valueFactory;
 
@@ -80,6 +84,8 @@ public class KiWiSparqlSailConnection extends 
NotifyingSailConnectionWrapper {
             new FilterOptimizer().optimize(tupleExpr, dataset, bindings);
             new OrderLimitOptimizer().optimize(tupleExpr, dataset, bindings);
 
+            log.debug("evaluating SPARQL query:\n {}", tupleExpr);
+
             return strategy.evaluate(tupleExpr, bindings);
 
         } catch (QueryEvaluationException e) {

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/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 81ddf6e..59455b8 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
@@ -211,6 +211,28 @@ public class KiWiSparqlJoinTest {
         testQuery("query2.sparql");
     }
 
+    @Test
+    public void testQuery3() throws Exception {
+        testQuery("query3.sparql");
+    }
+
+    @Test
+    public void testQuery4() throws Exception {
+        testQuery("query4.sparql");
+    }
+
+    // numeric operator
+    @Test
+    public void testQuery5() throws Exception {
+        testQuery("query5.sparql");
+    }
+
+    // language match
+    @Test
+    public void testQuery6() throws Exception {
+        testQuery("query6.sparql");
+    }
+
 
     private void testQuery(String filename) throws Exception {
         String queryString = 
IOUtils.toString(this.getClass().getResourceAsStream(filename), "UTF-8");

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/demo-data.foaf
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/demo-data.foaf
 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/demo-data.foaf
index c2d786b..bde1322 100644
--- 
a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/demo-data.foaf
+++ 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/demo-data.foaf
@@ -22,7 +22,8 @@
 
     <foaf:Person rdf:about="http://localhost:8080/LMF/resource/hans_meier"; 
xmlns:foaf="http://xmlns.com/foaf/0.1/";>
         <foaf:name>Hans Meier</foaf:name>
-        <dc:description>Hans Meier is a software engineer living in 
Salzburg</dc:description>
+        <dc:description xml:lang="en">Hans Meier is a software engineer living 
in Salzburg</dc:description>
+        <dc:description xml:lang="de">Hans Meier ist ein Softwareentwickler 
aus Salzburg</dc:description>
         <foaf:interest 
rdf:resource="http://rdf.freebase.com/ns/en.software_engineering"/>
         <foaf:interest rdf:resource="http://rdf.freebase.com/ns/en.linux"/>
         <foaf:interest rdf:resource="http://dbpedia.org/resource/Java"; />
@@ -30,6 +31,8 @@
         <foaf:based_near rdf:resource="http://sws.geonames.org/2766824/"/>
         <foaf:depiction 
rdf:resource="http://localhost:8080/LMF/resource/hans_meier.jpg"/>
 
+        <foaf:age 
rdf:datatype="http://www.w3.org/2001/XMLSchema#integer";>29</foaf:age>
+
         <foaf:knows 
rdf:resource="http://localhost:8080/LMF/resource/sepp_huber"; />
         <foaf:knows 
rdf:resource="http://localhost:8080/LMF/resource/anna_schmidt"/>
 
@@ -43,19 +46,23 @@
 
     <foaf:Person rdf:about="http://localhost:8080/LMF/resource/sepp_huber"; 
xmlns:foaf="http://xmlns.com/foaf/0.1/";>
         <foaf:name>Sepp Huber</foaf:name>
-        <dc:description>Sepp Huber is an alpinist living in Traunstein. He is 
a good climber, but not as famous as his cousin Alexander 
Huber.</dc:description>
+        <dc:description xml:lang="en">Sepp Huber is an alpinist living in 
Traunstein. He is a good climber, but not as famous as his cousin Alexander 
Huber.</dc:description>
+        <dc:description xml:lang="de-DE">Sepp Huber ist ein Bergsteiger aus 
Traunstein. Er ist ein guter Kletterer.</dc:description>
         <foaf:interest 
rdf:resource="http://dbpedia.org/resource/Mountaineering"/>
         <foaf:interest rdf:resource="http://dbpedia.org/resource/Climbing"/>
         <foaf:interest rdf:resource="http://localhost:8080/LMF/resource/Chess"; 
/>
         <foaf:based_near 
rdf:resource="http://dbpedia.org/resource/Traunstein"/>
 
+        <foaf:age 
rdf:datatype="http://www.w3.org/2001/XMLSchema#integer";>31</foaf:age>
+
+
         <foaf:knows rdf:resource="http://dbpedia.org/resource/Alexander_Huber"; 
/>
         <foaf:knows 
rdf:resource="http://localhost:8080/LMF/resource/hans_meier"; />
     </foaf:Person>
 
     <foaf:Person rdf:about="http://localhost:8080/LMF/resource/anna_schmidt"; 
xmlns:foaf="http://xmlns.com/foaf/0.1/";>
         <foaf:name>Anna Schmidt</foaf:name>
-        <dc:description>Anna Schmidt is working as PR manager for mountaineers 
coming from Garmisch-Partenkirchen. She likes mountaineering and is also a 
Linux enthusiast.</dc:description>
+        <dc:description xml:lang="en">Anna Schmidt is working as PR manager 
for mountaineers coming from Garmisch-Partenkirchen. She likes mountaineering 
and is also a Linux enthusiast.</dc:description>
         <foaf:interest 
rdf:resource="http://dbpedia.org/resource/Mountaineering"/>
         <foaf:interest rdf:resource="http://dbpedia.org/resource/Linux"/>
         <foaf:interest rdf:resource="http://localhost:8080/LMF/resource/Chess"; 
/>

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query3.sparql
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query3.sparql
 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query3.sparql
new file mode 100644
index 0000000..4e22987
--- /dev/null
+++ 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query3.sparql
@@ -0,0 +1,7 @@
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+
+SELECT ?p1 ?fn ?desc ?friend WHERE {
+    ?p1 foaf:name ?fn .
+    FILTER( regex(?fn, "Anna.*") )
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query4.sparql
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query4.sparql
 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query4.sparql
new file mode 100644
index 0000000..3cf4787
--- /dev/null
+++ 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query4.sparql
@@ -0,0 +1,7 @@
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+
+SELECT ?p1 ?fn ?desc ?friend WHERE {
+    ?p1 foaf:name ?fn .
+    FILTER( regex(str(?p1), "^http://localhost:8080/LMF/resource/sepp.*";) )
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query5.sparql
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query5.sparql
 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query5.sparql
new file mode 100644
index 0000000..325bb6b
--- /dev/null
+++ 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query5.sparql
@@ -0,0 +1,8 @@
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+
+SELECT ?p1 ?fn ?desc ?friend WHERE {
+    ?p1 foaf:name ?fn .
+    ?p1 foaf:age ?age .
+    FILTER( ?age > 30 )
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query6.sparql
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query6.sparql
 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query6.sparql
new file mode 100644
index 0000000..1a953df
--- /dev/null
+++ 
b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query6.sparql
@@ -0,0 +1,8 @@
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+
+SELECT ?p1 ?fn ?desc ?friend WHERE {
+    ?p1 foaf:name ?fn .
+    ?p1 dc:description ?d .
+    FILTER( langMatches(lang(?d), "de") )
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
index fa9834a..f7130d9 100644
--- 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
+++ 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
@@ -184,6 +184,10 @@ public class KiWiConnection {
         return cacheManager;
     }
 
+    public KiWiDialect getDialect() {
+        return dialect;
+    }
+
     /**
      * Load a KiWiNamespace with the given prefix, or null if the namespace 
does not exist. The method will first
      * look in the node cache for cached nodes. If no cache entry is found, it 
will run a database query
@@ -1361,8 +1365,8 @@ public class KiWiConnection {
 
     protected static Locale getLocale(String language) {
         Locale locale = localeMap.get(language);
-        if(locale == null) {
-            locale = LocaleUtils.toLocale(language);
+        if(locale == null && language != null) {
+            locale = LocaleUtils.toLocale(language.replace("-","_"));
             localeMap.put(language,locale);
 
         }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiDialect.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiDialect.java
 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiDialect.java
index 9cd130e..5e261c8 100644
--- 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiDialect.java
+++ 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiDialect.java
@@ -152,4 +152,24 @@ public abstract class KiWiDialect {
     public Set<String> getStatementIdentifiers() {
         return statements.stringPropertyNames();
     }
+
+
+    /**
+     * Return the database specific operator for matching a text against a 
regular expression.
+     *
+     * @param text
+     * @param pattern
+     * @return
+     */
+    public abstract String getRegexp(String text, String pattern);
+
+
+    /**
+     * Return the database specific case insensitive like comparison, e.g. 
ILIKE in Postgres.
+     *
+     * @param text
+     * @param pattern
+     * @return
+     */
+    public abstract String getILike(String text, String pattern);
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/h2/H2Dialect.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/h2/H2Dialect.java
 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/h2/H2Dialect.java
index dc57948..2be3575 100644
--- 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/h2/H2Dialect.java
+++ 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/h2/H2Dialect.java
@@ -44,4 +44,15 @@ public class H2Dialect extends KiWiDialect {
     public String getDriverClass() {
         return "org.h2.Driver";
     }
+
+    @Override
+    public String getRegexp(String text, String pattern) {
+        return text + " REGEXP " + pattern;
+    }
+
+    @Override
+    public String getILike(String text, String pattern) {
+        return "lower("+text+") LIKE lower("+pattern+")";
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
index 73722de..d4125e2 100644
--- 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
+++ 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
@@ -55,4 +55,14 @@ public class MySQLDialect extends KiWiDialect {
     public String getDriverClass() {
         return "com.mysql.jdbc.Driver";
     }
+
+    @Override
+    public String getRegexp(String text, String pattern) {
+        return text + " RLIKE " + pattern;
+    }
+
+    @Override
+    public String getILike(String text, String pattern) {
+        return "lower("+text+") LIKE lower("+pattern+")";
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
index c517d0f..1d7e875 100644
--- 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
+++ 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
@@ -45,4 +45,14 @@ public class PostgreSQLDialect extends KiWiDialect {
     public String getDriverClass() {
         return "org.postgresql.Driver";
     }
+
+    @Override
+    public String getRegexp(String text, String pattern) {
+        return text + " ~ " + pattern;
+    }
+
+    @Override
+    public String getILike(String text, String pattern) {
+        return text + " ILIKE " + pattern;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
----------------------------------------------------------------------
diff --git 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
index dc7c631..a6964ff 100644
--- 
a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
+++ 
b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
@@ -338,7 +338,7 @@ public class KiWiValueFactory implements ValueFactory {
         final KiWiUriResource rtype = (KiWiUriResource)createURI(type);
         final Locale locale;
         if(lang != null) {
-            locale = LocaleUtils.toLocale(lang);
+            locale = LocaleUtils.toLocale(lang.replace("-","_"));
         } else
             locale  = null;
 

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 2eb8e91..0e9a564 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1139,6 +1139,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.marmotta</groupId>
+                <artifactId>kiwi-sparql</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.marmotta</groupId>
                 <artifactId>kiwi-transactions</artifactId>
                 <version>${project.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/platform/marmotta-sparql/pom.xml
----------------------------------------------------------------------
diff --git a/platform/marmotta-sparql/pom.xml b/platform/marmotta-sparql/pom.xml
index 41970b7..ac86efb 100644
--- a/platform/marmotta-sparql/pom.xml
+++ b/platform/marmotta-sparql/pom.xml
@@ -138,6 +138,10 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.marmotta</groupId>
+            <artifactId>kiwi-sparql</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.openrdf.sesame</groupId>
             <artifactId>sesame-query</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sail/SPARQLSailProvider.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sail/SPARQLSailProvider.java
 
b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sail/SPARQLSailProvider.java
new file mode 100644
index 0000000..6b4112f
--- /dev/null
+++ 
b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sail/SPARQLSailProvider.java
@@ -0,0 +1,78 @@
+/*
+ * 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.platform.sparql.services.sail;
+
+import org.apache.marmotta.kiwi.sparql.sail.KiWiSparqlSail;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.triplestore.NotifyingSailProvider;
+import org.apache.marmotta.platform.core.api.triplestore.SesameService;
+import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
+import org.openrdf.sail.NotifyingSail;
+import org.openrdf.sail.helpers.NotifyingSailWrapper;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+
+/**
+ * This service wraps enhanced KiWi SPARQL support around the KiWi Store to 
improve the performance of typical
+ * SPARQL queries.
+ *
+ * @author Sebastian Schaffert ([email protected])
+ */
+@ApplicationScoped
+public class SPARQLSailProvider implements NotifyingSailProvider {
+
+    public static final String SPARQL_STRATEGY = "sparql.strategy";
+
+
+    @Inject
+    private ConfigurationService configurationService;
+
+    @Inject
+    private SesameService sesameService;
+
+    @Override
+    public NotifyingSailWrapper createSail(NotifyingSail parent) {
+        KiWiSparqlSail sail = new KiWiSparqlSail(parent);
+
+        return sail;
+    }
+
+    public void configurationChanged(@Observes ConfigurationChangedEvent e) {
+        if(e.containsChangedKey(SPARQL_STRATEGY)) {
+            sesameService.shutdown();
+            sesameService.initialise();
+        }
+    }
+
+
+    @Override
+    public String getName() {
+        return "SPARQL Optimizer";
+    }
+
+    @Override
+    public boolean isEnabled() {
+        
if("native".equalsIgnoreCase(configurationService.getStringConfiguration(SPARQL_STRATEGY)))
 {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/platform/marmotta-sparql/src/main/resources/config-defaults.properties
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-sparql/src/main/resources/config-defaults.properties 
b/platform/marmotta-sparql/src/main/resources/config-defaults.properties
index 529e817..ef5ff2e 100644
--- a/platform/marmotta-sparql/src/main/resources/config-defaults.properties
+++ b/platform/marmotta-sparql/src/main/resources/config-defaults.properties
@@ -25,31 +25,3 @@ sparql.allow_origin = *
 # SPARQL queries directly to database queries; more efficient but not tested 
extensively
 sparql.strategy = native
 
-
-# turn on/off fallback to Sesame in-memory SPARQL evaluation in case the 
default evaluation strategy fails for
-# whatever reason; this is a safe-guard option to always yield the correct 
results, but suffers the memory
-# and performance problems of the in-memory SPARQL evaulation
-sparql.fallback = true
-
-# select the way literal types are handled in SPARQL queries in case they are 
not correctly stored in the database
-# or not properly given in the query; value "strict" means that the evaluator 
always tries to cast a type
-# appropriately, but can result in considerable performance impacts; value 
"loose" means that all possible
-# types are used, ignoring the type specification; value "none" means that no 
type casting takes place, types
-# are used as given by the user (this is the most efficient setting, but may 
be less tolerant to faulty data or queries)
-sparql.native.casttype = none
-
-
-# log SQL statements to the lmf-main.log file for testing and debugging
-sparql.native.logsql = false
-
-
-# preload constant nodes in SPARQL expressions using the triple store 
functionality; constant values in SPARQL
-# expressions are substituted with the database ID of the respective nodes; 
setting this option to true
-# will reduce significantly the number of joins needed for a SPARQL query, but 
can require database access at
-# query construction time.
-sparql.native.preload_constants = true
-
-# interpret the SPARQL REDUCED query parameter as distinct; the specification 
for REDUCED says it is left to the
-# query optimizer whether to make results distinct or not; DISTINCT in SQL can 
introduce significant computational
-# overhead, so the default is false
-sparql.native.reduced_as_distinct = false

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/8f79ef1a/platform/marmotta-sparql/src/main/resources/config-descriptions.properties
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-sparql/src/main/resources/config-descriptions.properties 
b/platform/marmotta-sparql/src/main/resources/config-descriptions.properties
index bae7d61..2477ebf 100644
--- a/platform/marmotta-sparql/src/main/resources/config-descriptions.properties
+++ b/platform/marmotta-sparql/src/main/resources/config-descriptions.properties
@@ -24,34 +24,4 @@ sparql.allow_origin.type = java.lang.String
 
 sparql.strategy.description = select the SPARQL evaluation strategy to use 
(default: sesame); other settings than \
   "sesame" allow to translate SPARQL queries directly to database queries; 
more efficient but not tested extensively
-sparql.strategy.type = java.lang.Enum("native"|"sesame")
-
-
-sparql.fallback.description = turn on/off fallback to Sesame in-memory SPARQL 
evaluation in case the default \
-  evaluation strategy fails for whatever reason; this is a safe-guard option 
to always yield the correct results, \
-  but suffers the memory and performance problems of the in-memory SPARQL 
evaulation
-sparql.fallback.type = java.lang.Boolean
-
-sparql.native.casttype.description = select the way literal types are handled 
in SPARQL queries in case they are \
-  not correctly stored in the database or not properly given in the query; 
value "strict" means that the evaluator \
-  always tries to cast a type appropriately, but can result in considerable 
performance impacts; value "loose" means \
-  that all possible types are used, ignoring the type specification; value 
"none" means that no type casting takes \
-  place, types are used as given by the user (this is the most efficient 
setting, but may be less tolerant to faulty \
-  data or queries)
-sparql.native.casttype.type = java.lang.Enum("none"|"loose"|"strict")
-
-
-sparql.native.logsql.description = log SQL statements to the lmf-main.log file 
for testing and debugging
-sparql.native.logsql.type = java.lang.Boolean
-
-
-sparql.native.preload_constants.description = preload constant nodes in SPARQL 
expressions using the triple store \
-  functionality; constant values in SPARQL expressions are substituted with 
the database ID of the respective nodes; \
-  setting this option to true will reduce significantly the number of joins 
needed for a SPARQL query, but can require \
-  database access at query construction time.
-sparql.native.preload_constants.type = java.lang.Boolean
-
-sparql.native.reduced_as_distinct.description = interpret the SPARQL REDUCED 
query parameter as distinct; the \
-  specification for REDUCED says it is left to the query optimizer whether to 
make results distinct or not; DISTINCT \
-  in SQL can introduce significant computational overhead, so the default is 
false
-sparql.native.reduced_as_distinct.type = java.lang.Boolean
+sparql.strategy.type = java.lang.Enum("native"|"memory")
\ No newline at end of file

Reply via email to