Repository: marmotta Updated Branches: refs/heads/develop ff559ea4f -> c8f067f0f
prevents filter optimization if function is not implemented natively Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/b79a1621 Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/b79a1621 Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/b79a1621 Branch: refs/heads/develop Commit: b79a16213a403ab2bd82b3da714a6a681d046083 Parents: c008f95 Author: Thomas Kurz <[email protected]> Authored: Mon Nov 23 13:13:15 2015 +0100 Committer: Thomas Kurz <[email protected]> Committed: Mon Nov 23 13:13:15 2015 +0100 ---------------------------------------------------------------------- .../sparql/optimizer/NativeFilterOptimizer.java | 198 +++++++++++++++++++ .../sparql/sail/KiWiSparqlSailConnection.java | 5 +- 2 files changed, 201 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/b79a1621/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/optimizer/NativeFilterOptimizer.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/optimizer/NativeFilterOptimizer.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/optimizer/NativeFilterOptimizer.java new file mode 100644 index 0000000..5cde939 --- /dev/null +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/optimizer/NativeFilterOptimizer.java @@ -0,0 +1,198 @@ +package org.apache.marmotta.kiwi.sparql.optimizer; + +import org.apache.marmotta.kiwi.sparql.function.NativeFunctionRegistry; +import org.openrdf.model.URI; +import org.openrdf.query.BindingSet; +import org.openrdf.query.Dataset; +import org.openrdf.query.algebra.*; +import org.openrdf.query.algebra.evaluation.QueryOptimizer; +import org.openrdf.query.algebra.helpers.QueryModelVisitorBase; +import org.openrdf.query.algebra.helpers.VarNameCollector; + +import java.util.Set; + +/** + * @author Thomas Kurz ([email protected]) + * @since 23.11.15. + */ +public class NativeFilterOptimizer implements QueryOptimizer { + + @Override + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + FilterFinder f = new FilterFinder(tupleExpr); + tupleExpr.visit(f); + } + + /*--------------------------* + * Inner class FilterFinder * + *--------------------------*/ + + protected static class FilterFinder extends QueryModelVisitorBase<RuntimeException> { + + protected final TupleExpr tupleExpr; + + public FilterFinder(TupleExpr tupleExpr) { + this.tupleExpr = tupleExpr; + } + + @Override + public void meet(Filter filter) { + super.meet(filter); + if(filter.getCondition() instanceof FunctionCall) { + String uri = ((FunctionCall) filter.getCondition()).getURI(); + if(NativeFunctionRegistry.getInstance().get(uri) != null) { + FilterRelocator.relocate(filter); + } + } else { + FilterRelocator.relocate(filter); + } + } + } + + + /*-----------------------------* + * Inner class FilterRelocator * + *-----------------------------*/ + + protected static class FilterRelocator extends QueryModelVisitorBase<RuntimeException> { + + public static void relocate(Filter filter) { + filter.visit(new FilterRelocator(filter)); + } + + protected final Filter filter; + + protected final Set<String> filterVars; + + public FilterRelocator(Filter filter) { + this.filter = filter; + filterVars = VarNameCollector.process(filter.getCondition()); + } + + @Override + protected void meetNode(QueryModelNode node) { + // By default, do not traverse + assert node instanceof TupleExpr; + relocate(filter, (TupleExpr) node); + } + + @Override + public void meet(Join join) { + if (join.getLeftArg().getBindingNames().containsAll(filterVars)) { + // All required vars are bound by the left expr + join.getLeftArg().visit(this); + } + else if (join.getRightArg().getBindingNames().containsAll(filterVars)) { + // All required vars are bound by the right expr + join.getRightArg().visit(this); + } + else { + relocate(filter, join); + } + } + + @Override + public void meet(LeftJoin leftJoin) { + if (leftJoin.getLeftArg().getBindingNames().containsAll(filterVars)) { + leftJoin.getLeftArg().visit(this); + } + else { + relocate(filter, leftJoin); + } + } + + @Override + public void meet(Union union) { + Filter clone = new Filter(); + clone.setCondition(filter.getCondition().clone()); + + relocate(filter, union.getLeftArg()); + relocate(clone, union.getRightArg()); + + FilterRelocator.relocate(filter); + FilterRelocator.relocate(clone); + } + + @Override + public void meet(Difference node) { + Filter clone = new Filter(); + clone.setCondition(filter.getCondition().clone()); + + relocate(filter, node.getLeftArg()); + relocate(clone, node.getRightArg()); + + FilterRelocator.relocate(filter); + FilterRelocator.relocate(clone); + } + + @Override + public void meet(Intersection node) { + Filter clone = new Filter(); + clone.setCondition(filter.getCondition().clone()); + + relocate(filter, node.getLeftArg()); + relocate(clone, node.getRightArg()); + + FilterRelocator.relocate(filter); + FilterRelocator.relocate(clone); + } + + @Override + public void meet(Extension node) { + if (node.getArg().getBindingNames().containsAll(filterVars)) { + node.getArg().visit(this); + } + else { + relocate(filter, node); + } + } + + @Override + public void meet(EmptySet node) { + if (filter.getParentNode() != null) { + // Remove filter from its original location + filter.replaceWith(filter.getArg()); + } + } + + @Override + public void meet(Filter filter) { + // Filters are commutative + filter.getArg().visit(this); + } + + @Override + public void meet(Distinct node) { + node.getArg().visit(this); + } + + @Override + public void meet(Order node) { + node.getArg().visit(this); + } + + @Override + public void meet(QueryRoot node) { + node.getArg().visit(this); + } + + @Override + public void meet(Reduced node) { + node.getArg().visit(this); + } + + protected void relocate(Filter filter, TupleExpr newFilterArg) { + if (filter.getArg() != newFilterArg) { + if (filter.getParentNode() != null) { + // Remove filter from its original location + filter.replaceWith(filter.getArg()); + } + + // Insert filter at the new location + newFilterArg.replaceWith(filter); + filter.setArg(newFilterArg); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/marmotta/blob/b79a1621/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 09333e7..3c77ead 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 @@ -25,6 +25,7 @@ import org.apache.marmotta.kiwi.sparql.evaluation.KiWiEvaluationStrategy; import org.apache.marmotta.kiwi.sparql.evaluation.KiWiTripleSource; import org.apache.marmotta.kiwi.sparql.optimizer.DifferenceOptimizer; import org.apache.marmotta.kiwi.sparql.optimizer.DistinctLimitOptimizer; +import org.apache.marmotta.kiwi.sparql.optimizer.NativeFilterOptimizer; import org.openrdf.query.BindingSet; import org.openrdf.query.Dataset; import org.openrdf.query.QueryEvaluationException; @@ -81,11 +82,11 @@ public class KiWiSparqlSailConnection extends NotifyingSailConnectionWrapper { //new DisjunctiveConstraintOptimizer().optimize(tupleExpr, dataset, bindings); //new SameTermFilterOptimizer().optimize(tupleExpr, dataset, bindings); - new QueryModelNormalizer().optimize(tupleExpr, dataset, bindings); new QueryJoinOptimizer(new KiWiEvaluationStatistics()).optimize(tupleExpr, dataset, bindings); new IterativeEvaluationOptimizer().optimize(tupleExpr, dataset, bindings); - new FilterOptimizer().optimize(tupleExpr, dataset, bindings); + + new NativeFilterOptimizer().optimize(tupleExpr, dataset, bindings); //new OrderLimitOptimizer().optimize(tupleExpr, dataset, bindings); new DistinctLimitOptimizer().optimize(tupleExpr, dataset, bindings);
