You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rya.apache.org by mi...@apache.org on 2017/08/03 04:47:26 UTC

[3/3] incubator-rya git commit: RYA-323 Enabling Multi Var Geo Functions. Closes #183

RYA-323 Enabling Multi Var Geo Functions. Closes #183


Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/94911ed8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/94911ed8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/94911ed8

Branch: refs/heads/master
Commit: 94911ed894e48c52ea5f69af6f1ac41c752c7a3e
Parents: 5e26bbe
Author: Aaron Mihalik <mi...@alum.mit.edu>
Authored: Tue Jul 25 13:43:03 2017 -0400
Committer: Aaron Mihalik <aa...@gmail.com>
Committed: Thu Aug 3 00:28:34 2017 -0400

----------------------------------------------------------------------
 .../org/apache/rya/indexing/IndexingExpr.java   |   6 +-
 .../rya/indexing/IndexingFunctionRegistry.java  |   2 +
 .../apache/rya/indexing/TemporalTupleSet.java   |   3 +-
 .../accumulo/freetext/FreeTextTupleSet.java     |   3 +-
 .../GeoEnabledFilterFunctionOptimizer.java      |   4 +-
 .../indexing/accumulo/geo/GeoParseUtils.java    |   6 +-
 .../rya/indexing/accumulo/geo/GeoTupleSet.java  |  21 +-
 .../GeoTemporalMongoDBStorageStrategy.java      |   5 +-
 .../indexing/mongodb/geo/MongoGeoTupleSet.java  | 361 +++++++++++++++++++
 .../evaluation/QueryJoinOptimizer.java          |  21 +-
 10 files changed, 413 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingExpr.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingExpr.java b/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingExpr.java
index 37e98af..f919b18 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingExpr.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingExpr.java
@@ -32,10 +32,10 @@ import com.google.common.collect.Sets;
 public class IndexingExpr {
 
     private final URI function;
-    private final Value[] arguments;
+    private final Object[] arguments;
     private final StatementPattern spConstraint;
 
-    public IndexingExpr(URI function, StatementPattern spConstraint, Value... arguments) {
+    public IndexingExpr(URI function, StatementPattern spConstraint, Object... arguments) {
         this.function = function;
         this.arguments = arguments;
         this.spConstraint = spConstraint;
@@ -45,7 +45,7 @@ public class IndexingExpr {
         return function;
     }
 
-    public Value[] getArguments() {
+    public Object[] getArguments() {
         return arguments;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingFunctionRegistry.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingFunctionRegistry.java b/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingFunctionRegistry.java
index b61af4b..37f7116 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingFunctionRegistry.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/IndexingFunctionRegistry.java
@@ -115,6 +115,8 @@ public class IndexingFunctionRegistry {
                 return (Var) arg1;
             else if (isUnboundVariable(arg2) && isConstant(arg1))
                 return (Var) arg2;
+            else 
+                return (Var) arg1;
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/indexing/src/main/java/org/apache/rya/indexing/TemporalTupleSet.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/TemporalTupleSet.java b/extras/indexing/src/main/java/org/apache/rya/indexing/TemporalTupleSet.java
index 7cb4e6c..3f20191 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/TemporalTupleSet.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/TemporalTupleSet.java
@@ -8,6 +8,7 @@ import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.joda.time.DateTime;
 import org.openrdf.model.Statement;
 import org.openrdf.model.URI;
+import org.openrdf.model.Value;
 import org.openrdf.model.impl.URIImpl;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.QueryEvaluationException;
@@ -117,7 +118,7 @@ public class TemporalTupleSet extends ExternalTupleSet {
             throw new IllegalArgumentException("Index functions do not support more than two arguments.");
         }
 
-        final String queryText = filterInfo.getArguments()[0].stringValue();
+        final String queryText = ((Value) filterInfo.getArguments()[0]).stringValue();
         return IteratorFactory.getIterator(filterInfo.getSpConstraint(), bindings, queryText, searchFunction);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/FreeTextTupleSet.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/FreeTextTupleSet.java b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/FreeTextTupleSet.java
index 6b01811..383b969 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/FreeTextTupleSet.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/FreeTextTupleSet.java
@@ -35,6 +35,7 @@ import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.hadoop.conf.Configuration;
 import org.openrdf.model.Statement;
 import org.openrdf.model.URI;
+import org.openrdf.model.Value;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.QueryEvaluationException;
 import org.openrdf.query.algebra.QueryModelVisitor;
@@ -152,7 +153,7 @@ public class FreeTextTupleSet extends ExternalTupleSet {
             throw new IllegalArgumentException("Index functions do not support more than two arguments.");
         }
 
-        String queryText = filterInfo.getArguments()[0].stringValue();
+        String queryText = ((Value) filterInfo.getArguments()[0]).stringValue();
 
         return IteratorFactory.getIterator(filterInfo.getSpConstraint(), bindings, queryText, searchFunction);
     }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/GeoEnabledFilterFunctionOptimizer.java
----------------------------------------------------------------------
diff --git a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/GeoEnabledFilterFunctionOptimizer.java b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/GeoEnabledFilterFunctionOptimizer.java
index bf6b632..b7c49d8 100644
--- a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/GeoEnabledFilterFunctionOptimizer.java
+++ b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/GeoEnabledFilterFunctionOptimizer.java
@@ -207,13 +207,13 @@ public class GeoEnabledFilterFunctionOptimizer implements QueryOptimizer, Config
     private abstract class AbstractEnhanceVisitor extends QueryModelVisitorBase<RuntimeException> {
         final String matchVar;
         List<URI> func = Lists.newArrayList();
-        List<Value[]> args = Lists.newArrayList();
+        List<Object[]> args = Lists.newArrayList();
 
         public AbstractEnhanceVisitor(final String matchVar) {
             this.matchVar = matchVar;
         }
 
-        protected void addFilter(final URI uri, final Value[] values) {
+        protected void addFilter(final URI uri, final Object[] values) {
             func.add(uri);
             args.add(values);
         }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoParseUtils.java
----------------------------------------------------------------------
diff --git a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoParseUtils.java b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoParseUtils.java
index e8fbc3d..103b241 100644
--- a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoParseUtils.java
+++ b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoParseUtils.java
@@ -126,8 +126,8 @@ public class GeoParseUtils {
      * @param call - The {@link FunctionCall} to match against.
      * @return - The {@link Value}s matched.
      */
-    public static Value[] extractArguments(final String matchName, final FunctionCall call) {
-        final Value args[] = new Value[call.getArgs().size() - 1];
+    public static Object[] extractArguments(final String matchName, final FunctionCall call) {
+        final Object[] args = new Object[call.getArgs().size() - 1];
         int argI = 0;
         for (int i = 0; i != call.getArgs().size(); ++i) {
             final ValueExpr arg = call.getArgs().get(i);
@@ -139,7 +139,7 @@ public class GeoParseUtils {
             } else if (arg instanceof Var && ((Var)arg).hasValue()) {
                 args[argI] = ((Var)arg).getValue();
             } else {
-                throw new IllegalArgumentException("Query error: Found " + arg + ", expected a Literal, BNode or URI");
+                args[argI] = arg;
             }
             ++argI;
         }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoTupleSet.java
----------------------------------------------------------------------
diff --git a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoTupleSet.java b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoTupleSet.java
index 3f4be9c..8cdeb5c 100644
--- a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoTupleSet.java
+++ b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/accumulo/geo/GeoTupleSet.java
@@ -20,6 +20,7 @@ import org.openrdf.model.URI;
 import org.openrdf.model.Value;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.algebra.Var;
 
 import com.google.common.base.Joiner;
 import com.google.common.collect.Maps;
@@ -123,7 +124,15 @@ public class GeoTupleSet extends ExternalTupleSet {
         final URI funcURI = filterInfo.getFunction();
         final SearchFunction searchFunction = new GeoSearchFunctionFactory(conf, geoIndexer).getSearchFunction(funcURI);
 
-        String queryText = filterInfo.getArguments()[0].stringValue();
+        String queryText;
+        Object arg = filterInfo.getArguments()[0];
+        if (arg instanceof Value) {
+            queryText = ((Value) arg).stringValue();
+        } else if (arg instanceof Var) {
+            queryText = bindings.getBinding(((Var) arg).getName()).getValue().stringValue();
+        } else {
+            throw new IllegalArgumentException("Query text was not resolved");
+        }
 
         if(funcURI.equals(GeoConstants.GEO_SF_NEAR)) {
             if (filterInfo.getArguments().length > 3) {
@@ -131,8 +140,14 @@ public class GeoTupleSet extends ExternalTupleSet {
             }
 
             final List<String> valueList = new ArrayList<>();
-            for (final Value val : filterInfo.getArguments()) {
-                valueList.add(val.stringValue());
+            for (final Object val : filterInfo.getArguments()) {
+                if (val instanceof Value) {
+                    valueList.add(((Value)val).stringValue());
+                } else if (val instanceof Var) {
+                    valueList.add(bindings.getBinding(((Var) val).getName()).getValue().stringValue());
+                } else {
+                    throw new IllegalArgumentException("Query text was not resolved");
+                }
             }
             queryText = Strings.join(valueList, NEAR_DELIM);
         } else if (filterInfo.getArguments().length > 1) {

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/geotemporal/mongo/GeoTemporalMongoDBStorageStrategy.java
----------------------------------------------------------------------
diff --git a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/geotemporal/mongo/GeoTemporalMongoDBStorageStrategy.java b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/geotemporal/mongo/GeoTemporalMongoDBStorageStrategy.java
index bc79de4..6e8ed99 100644
--- a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/geotemporal/mongo/GeoTemporalMongoDBStorageStrategy.java
+++ b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/geotemporal/mongo/GeoTemporalMongoDBStorageStrategy.java
@@ -49,6 +49,7 @@ import org.apache.rya.indexing.mongodb.temporal.TemporalMongoDBStorageStrategy;
 import org.joda.time.DateTime;
 import org.openrdf.model.Statement;
 import org.openrdf.model.URI;
+import org.openrdf.model.Value;
 import org.openrdf.query.MalformedQueryException;
 
 import com.mongodb.BasicDBObject;
@@ -144,7 +145,7 @@ public class GeoTemporalMongoDBStorageStrategy extends IndexingMongoDBStorageStr
         geoFilters.forEach(filter -> {
             final GeoPolicy policy = GeoPolicy.fromURI(filter.getFunction());
             final WKTReader reader = new WKTReader();
-            final String geoStr = filter.getArguments()[0].stringValue();
+            final String geoStr = ((Value) filter.getArguments()[0]).stringValue();
             try {
                 //This method is what is used in the GeoIndexer.
                 final Geometry geo = reader.read(geoStr);
@@ -160,7 +161,7 @@ public class GeoTemporalMongoDBStorageStrategy extends IndexingMongoDBStorageStr
         final List<DBObject> objs = new ArrayList<>();
         temporalFilters.forEach(filter -> {
             final TemporalPolicy policy = TemporalPolicy.fromURI(filter.getFunction());
-            final String timeStr = filter.getArguments()[0].stringValue();
+            final String timeStr = ((Value) filter.getArguments()[0]).stringValue();
             final Matcher matcher = TemporalInstantRfc3339.PATTERN.matcher(timeStr);
             if(matcher.find()) {
                 final TemporalInterval interval = TemporalInstantRfc3339.parseInterval(timeStr);

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/mongodb/geo/MongoGeoTupleSet.java
----------------------------------------------------------------------
diff --git a/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/mongodb/geo/MongoGeoTupleSet.java b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/mongodb/geo/MongoGeoTupleSet.java
new file mode 100644
index 0000000..c564d02
--- /dev/null
+++ b/extras/rya.geoindexing/src/main/java/org/apache/rya/indexing/mongodb/geo/MongoGeoTupleSet.java
@@ -0,0 +1,361 @@
+package org.apache.rya.indexing.mongodb.geo;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.hadoop.conf.Configuration;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryEvaluationException;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Maps;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.io.ParseException;
+import com.vividsolutions.jts.io.WKTReader;
+
+/*
+ * 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.
+ */
+
+
+import info.aduna.iteration.CloseableIteration;
+import org.apache.rya.indexing.GeoConstants;
+import org.apache.rya.indexing.GeoIndexer;
+import org.apache.rya.indexing.IndexingExpr;
+import org.apache.rya.indexing.IteratorFactory;
+import org.apache.rya.indexing.SearchFunction;
+import org.apache.rya.indexing.StatementConstraints;
+import org.apache.rya.indexing.accumulo.geo.GeoTupleSet;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+
+public class MongoGeoTupleSet extends ExternalTupleSet {
+
+    private Configuration conf;
+    private GeoIndexer geoIndexer;
+    private IndexingExpr filterInfo;
+   
+
+    public MongoGeoTupleSet(IndexingExpr filterInfo, GeoIndexer geoIndexer) {
+        this.filterInfo = filterInfo;
+        this.geoIndexer = geoIndexer;
+        this.conf = geoIndexer.getConf();
+    }
+
+    @Override
+    public Set<String> getBindingNames() {
+        return filterInfo.getBindingNames();
+    }
+
+    public GeoTupleSet clone() {
+        return new GeoTupleSet(filterInfo, geoIndexer);
+    }
+
+    @Override
+    public double cardinality() {
+        return 0.0; // No idea how the estimate cardinality here.
+    }
+    
+   
+    @Override
+    public String getSignature() {
+        return "(GeoTuple Projection) " + "variables: " + Joiner.on(", ").join(this.getBindingNames()).replaceAll("\\s+", " ");
+    }
+    
+    
+    
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if (!(other instanceof MongoGeoTupleSet)) {
+            return false;
+        }
+        MongoGeoTupleSet arg = (MongoGeoTupleSet) other;
+        return this.filterInfo.equals(arg.filterInfo);
+    }
+    
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31*result + filterInfo.hashCode();
+        
+        return result;
+    }
+    
+    
+
+    /**
+     * Returns an iterator over the result set of the contained IndexingExpr.
+     * <p>
+     * Should be thread-safe (concurrent invocation {@link OfflineIterable} this
+     * method can be expected with some query evaluators.
+     */
+    @Override
+    public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(BindingSet bindings)
+            throws QueryEvaluationException {
+        
+      
+        URI funcURI = filterInfo.getFunction();
+        SearchFunction searchFunction = (new MongoGeoSearchFunctionFactory(conf)).getSearchFunction(funcURI);
+        if(filterInfo.getArguments().length > 1) {
+            throw new IllegalArgumentException("Index functions do not support more than two arguments.");
+        }
+
+        String queryText = ((Value) filterInfo.getArguments()[0]).stringValue();
+        
+        return IteratorFactory.getIterator(filterInfo.getSpConstraint(), bindings, queryText, searchFunction);
+    }
+
+
+    
+    //returns appropriate search function for a given URI
+    //search functions used in GeoMesaGeoIndexer to access index
+    public class MongoGeoSearchFunctionFactory {
+        
+        Configuration conf;
+        
+        private final Map<URI, SearchFunction> SEARCH_FUNCTION_MAP = Maps.newHashMap();
+
+        public MongoGeoSearchFunctionFactory(Configuration conf) {
+            this.conf = conf;
+        }
+        
+
+        /**
+         * Get a {@link GeoSearchFunction} for a given URI.
+         * 
+         * @param searchFunction
+         * @return
+         */
+        public SearchFunction getSearchFunction(final URI searchFunction) {
+
+            SearchFunction geoFunc = null;
+
+            try {
+                geoFunc = getSearchFunctionInternal(searchFunction);
+            } catch (QueryEvaluationException e) {
+                e.printStackTrace();
+            }
+
+            return geoFunc;
+        }
+
+        private SearchFunction getSearchFunctionInternal(final URI searchFunction) throws QueryEvaluationException {
+            SearchFunction sf = SEARCH_FUNCTION_MAP.get(searchFunction);
+
+            if (sf != null) {
+                return sf;
+            } else {
+                throw new QueryEvaluationException("Unknown Search Function: " + searchFunction.stringValue());
+            }
+        }
+
+        private final SearchFunction GEO_EQUALS = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_EQUALS";
+            };
+        };
+
+        private final SearchFunction GEO_DISJOINT = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_DISJOINT";
+            };
+        };
+
+        private final SearchFunction GEO_INTERSECTS = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_INTERSECTS";
+            };
+        };
+
+        private final SearchFunction GEO_TOUCHES = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_TOUCHES";
+            };
+        };
+
+        private final SearchFunction GEO_CONTAINS = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_CONTAINS";
+            };
+        };
+
+        private final SearchFunction GEO_OVERLAPS = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_OVERLAPS";
+            };
+        };
+
+        private final SearchFunction GEO_CROSSES = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_CROSSES";
+            };
+        };
+
+        private final SearchFunction GEO_WITHIN = new SearchFunction() {
+
+            @Override
+            public CloseableIteration<Statement, QueryEvaluationException> performSearch(String queryText,
+                    StatementConstraints contraints) throws QueryEvaluationException {
+                try {
+                    WKTReader reader = new WKTReader();
+                    Geometry geometry = reader.read(queryText);
+                    CloseableIteration<Statement, QueryEvaluationException> statements = geoIndexer.queryWithin(
+                            geometry, contraints);
+                    return statements;
+                } catch (ParseException e) {
+                    throw new QueryEvaluationException(e);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "GEO_WITHIN";
+            };
+        };
+
+        {
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_EQUALS, GEO_EQUALS);
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_DISJOINT, GEO_DISJOINT);
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_INTERSECTS, GEO_INTERSECTS);
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_TOUCHES, GEO_TOUCHES);
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_CONTAINS, GEO_CONTAINS);
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_OVERLAPS, GEO_OVERLAPS);
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_CROSSES, GEO_CROSSES);
+            SEARCH_FUNCTION_MAP.put(GeoConstants.GEO_SF_WITHIN, GEO_WITHIN);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/94911ed8/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/QueryJoinOptimizer.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/QueryJoinOptimizer.java b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/QueryJoinOptimizer.java
index 2cb02ba..b5d5c43 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/QueryJoinOptimizer.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/QueryJoinOptimizer.java
@@ -1,5 +1,14 @@
 package org.apache.rya.rdftriplestore.evaluation;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.rya.rdftriplestore.utils.DefaultStatistics;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -23,14 +32,16 @@ package org.apache.rya.rdftriplestore.evaluation;
 
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.Dataset;
-import org.openrdf.query.algebra.*;
+import org.openrdf.query.algebra.Join;
+import org.openrdf.query.algebra.LeftJoin;
+import org.openrdf.query.algebra.StatementPattern;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.Var;
 import org.openrdf.query.algebra.evaluation.QueryOptimizer;
 import org.openrdf.query.algebra.evaluation.impl.EvaluationStatistics;
 import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
 import org.openrdf.query.algebra.helpers.StatementPatternCollector;
 
-import java.util.*;
-
 /**
  * A query optimizer that re-orders nested Joins.
  *
@@ -56,7 +67,9 @@ public class QueryJoinOptimizer implements QueryOptimizer {
      * @param tupleExpr
      */
     public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) {
-        tupleExpr.visit(new JoinVisitor());
+        if (!(statistics instanceof DefaultStatistics)) {
+            tupleExpr.visit(new JoinVisitor());
+        }
     }
 
     protected class JoinVisitor extends QueryModelVisitorBase<RuntimeException> {