Updated Branches: refs/heads/develop 288b90439 -> b44e655b5
minor bug fixes and comment improvements for SPARQL optimizer Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/b44e655b Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/b44e655b Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/b44e655b Branch: refs/heads/develop Commit: b44e655b527dc2ca962fd3f003dbaaee395caa69 Parents: 288b904 Author: Sebastian Schaffert <[email protected]> Authored: Tue Apr 30 10:50:38 2013 +0200 Committer: Sebastian Schaffert <[email protected]> Committed: Tue Apr 30 10:50:38 2013 +0200 ---------------------------------------------------------------------- .../evaluation/KiWiEvaluationStrategyImpl.java | 25 ++++++++++++-- .../sparql/persistence/KiWiSparqlConnection.java | 23 +++++++++----- .../marmotta/kiwi/persistence/KiWiDialect.java | 9 +++++ .../marmotta/kiwi/persistence/h2/H2Dialect.java | 16 +++++++++ .../kiwi/persistence/mysql/MySQLDialect.java | 15 +++++++++ .../kiwi/persistence/pgsql/PostgreSQLDialect.java | 17 ++++++++++ 6 files changed, 93 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b44e655b/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 9fab185..1f667eb 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 @@ -32,7 +32,16 @@ import org.slf4j.LoggerFactory; import java.sql.SQLException; /** - * An implementation of the SPARQL query evaluation strategy with specific extensions and optimizations. + * An implementation of the SPARQL query evaluation strategy with specific extensions and optimizations. The KiWi + * evaluation strategy is able to apply optimizations to certain frequently found query patterns by directly translating + * them into SQL queries. Currently, the following constructs are supported: + * <ul> + * <li>JOINs of statement patterns are translated into SQL joins (no OPTIONAL and no path expressions supporterd)</li> + * <li>FILTERs are translated to SQL where conditions, in case the FILTER conditions are supported (no aggregation constructs are supported)</li> + * </ul> + * In case a query is not completely supported by the optimizer, the optimizer might still improve performance by + * evaluating the optimizable components of the query and then letting the in-memory implementation take over + * (e.g. for aggregation constructs, distinct, path expressions, optional). * * @author Sebastian Schaffert ([email protected]) */ @@ -80,7 +89,7 @@ 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 ..."); + log.debug("applying KiWi FILTER optimizations on SPARQL query ..."); try { return new ExceptionConvertingIteration<BindingSet, QueryEvaluationException>(connection.evaluateJoin(join, bindings)) { @@ -101,7 +110,7 @@ public class KiWiEvaluationStrategyImpl extends EvaluationStrategyImpl{ /** - * Test if a join consists only of joins of statement patterns; in this case we can apply a specific optimization. + * Test if a tuple expression is supported nby the optimized evaluation; in this case we can apply a specific optimization. * @param expr * @return */ @@ -117,7 +126,13 @@ public class KiWiEvaluationStrategyImpl extends EvaluationStrategyImpl{ } } - + /** + * Test if the value expression construct and all its subexpressions are supported by the optimized evaluation + * strategy. Returns true if yes, false otherwise. + * + * @param expr + * @return + */ private static boolean isSupported(ValueExpr expr) { if(expr instanceof Compare) { return isSupported(((Compare) expr).getLeftArg()) && isSupported(((Compare) expr).getRightArg()); @@ -127,6 +142,8 @@ public class KiWiEvaluationStrategyImpl extends EvaluationStrategyImpl{ 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 Not) { + return isSupported(((Not) expr).getArg()); } else if(expr instanceof ValueConstant) { return true; } else if(expr instanceof Var) { http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b44e655b/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 e2f405c..0772e4c 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 @@ -69,7 +69,7 @@ public class KiWiSparqlConnection { } /** - * Evaluate a statement pattern join on the database by translating it into an appropriate SQL statement. + * Evaluate a statement pattern join or filter on the database by translating it into an appropriate SQL statement. * Copied and adapted from KiWiReasoningConnection.query() * @param join * @return @@ -316,6 +316,8 @@ public class KiWiSparqlConnection { 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 Not) { + return "NOT (" + evaluateExpression(((Not) expr).getArg(), queryVariables, optype) + ")"; } else if(expr instanceof Str) { Str str = (Str)expr; // get value of argument and express it as string @@ -349,13 +351,18 @@ public class KiWiSparqlConnection { OPTypes ot = determineOpType(cmp.getLeftArg(), cmp.getRightArg()); - return evaluateExpression(cmp.getLeftArg(),queryVariables, ot) + getSQLOperator(cmp.getOperator()) + evaluateExpression(cmp.getRightArg(),queryVariables, ot); + if(ot == OPTypes.STRING) { + if(cmp.getOperator() == MathExpr.MathOp.PLUS) { + return parent.getDialect().getConcat(evaluateExpression(cmp.getLeftArg(),queryVariables, ot), evaluateExpression(cmp.getRightArg(),queryVariables, ot)); + } else { + throw new IllegalArgumentException("operation "+cmp.getOperator()+" is not supported on strings"); + } + } else { + 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)); return optimizeRegexp(evaluateExpression(re.getArg(),queryVariables, optype), evaluateExpression(re.getPatternArg(), queryVariables, OPTypes.STRING)); } else if(expr instanceof LangMatches) { LangMatches lm = (LangMatches)expr; @@ -435,9 +442,9 @@ public class KiWiSparqlConnection { } 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) + "'"; + case INT: return "" + Integer.parseInt(val); + case DOUBLE: return "" + Double.parseDouble(val); + case DATE: return "'" + sqlDateFormat.format(DateUtils.parseDate(val)) + "'"; default: throw new IllegalArgumentException("unsupported value type: " + optype); } } http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b44e655b/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 5e261c8..0d66088 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 @@ -172,4 +172,13 @@ public abstract class KiWiDialect { * @return */ public abstract String getILike(String text, String pattern); + + + /** + * Get the database specific string concatenation function for the (variable number of) arguments. + * + * @param args + * @return + */ + public abstract String getConcat(String... args); } http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b44e655b/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 2be3575..7a1c1ee 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 @@ -55,4 +55,20 @@ public class H2Dialect extends KiWiDialect { return "lower("+text+") LIKE lower("+pattern+")"; } + + + @Override + public String getConcat(String... args) { + StringBuilder buf = new StringBuilder(); + buf.append("CONCAT("); + for(int i=0; i<args.length; i++) { + buf.append(args[i]); + if(i + 1 <args.length) { + buf.append(","); + } + } + buf.append(")"); + return buf.toString(); + } + } http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b44e655b/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 d4125e2..7d147fa 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 @@ -65,4 +65,19 @@ public class MySQLDialect extends KiWiDialect { public String getILike(String text, String pattern) { return "lower("+text+") LIKE lower("+pattern+")"; } + + + @Override + public String getConcat(String... args) { + StringBuilder buf = new StringBuilder(); + buf.append("CONCAT("); + for(int i=0; i<args.length; i++) { + buf.append(args[i]); + if(i + 1 <args.length) { + buf.append(","); + } + } + buf.append(")"); + return buf.toString(); + } } http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b44e655b/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 1d7e875..d9ebd4a 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 @@ -55,4 +55,21 @@ public class PostgreSQLDialect extends KiWiDialect { public String getILike(String text, String pattern) { return text + " ILIKE " + pattern; } + + + + @Override + public String getConcat(String... args) { + StringBuilder buf = new StringBuilder(); + buf.append("("); + for(int i=0; i<args.length; i++) { + buf.append(args[i]); + if(i + 1 <args.length) { + buf.append("||"); + } + } + buf.append(")"); + return buf.toString(); + } + }
