Fixed a severe bug in SubgraphStrategy where infinite recurssion occurs if the strategy is not smart about how child traverals with Vertex/EdgeSteps are analyzed. Also Deprecated vertexCriteria() method with vertices() likewise for edgeCritera() in SubGraphStrategy.Builder to be consistent with GraphFilter style (same concept). In fact, moving forward, SubGraphStrategy could take a GraphFilter.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9d6a4957 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9d6a4957 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9d6a4957 Branch: refs/heads/TINKERPOP-1278 Commit: 9d6a4957468a65d15180ddc31f5020255ad14f20 Parents: 8f7218d Author: Marko A. Rodriguez <okramma...@gmail.com> Authored: Fri Aug 5 13:16:58 2016 -0600 Committer: Marko A. Rodriguez <okramma...@gmail.com> Committed: Fri Aug 5 13:16:58 2016 -0600 ---------------------------------------------------------------------- .../strategy/decoration/SubgraphStrategy.java | 120 +++++++++++++------ .../decoration/SubgraphStrategyTest.java | 22 ++++ .../decoration/SubgraphStrategyProcessTest.java | 58 +++++---- .../SparkStarBarrierInterceptor.java | 4 + 4 files changed, 144 insertions(+), 60 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d6a4957/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java index d328168..82fffaa 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java @@ -22,23 +22,26 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeOtherVertexStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep; -import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep; import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Element; +import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; /** @@ -48,75 +51,98 @@ import java.util.stream.Collectors; * it traverses and returns. * * @author Stephen Mallette (http://stephen.genoprime.com) + * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class SubgraphStrategy extends AbstractTraversalStrategy<TraversalStrategy.DecorationStrategy> implements TraversalStrategy.DecorationStrategy { - private final Traversal<Vertex, ?> vertexCriterion; - private final Traversal<Edge, ?> edgeCriterion; + private final Traversal.Admin<Vertex, ?> vertexCriterion; + private final Traversal.Admin<Edge, ?> edgeCriterion; + private final String MARKER = Graph.Hidden.hide(UUID.randomUUID().toString()); private SubgraphStrategy(final Traversal<Vertex, ?> vertexCriterion, final Traversal<Edge, ?> edgeCriterion) { - this.vertexCriterion = vertexCriterion; + this.vertexCriterion = null == vertexCriterion ? null : vertexCriterion.asAdmin(); // if there is no vertex predicate there is no need to test either side of the edge - if (null == vertexCriterion) { - this.edgeCriterion = edgeCriterion; + if (null == this.vertexCriterion) { + this.edgeCriterion = null == edgeCriterion ? null : edgeCriterion.asAdmin(); } else { - final Traversal<Object, Vertex> inVertexPredicate = __.inV().filter(vertexCriterion); - final Traversal<Object, Vertex> outVertexPredicate = __.outV().filter(vertexCriterion); + final Traversal.Admin<Edge, ?> vertexPredicate = __.<Edge>and( + __.inV().filter(this.vertexCriterion.clone()), + __.outV().filter(this.vertexCriterion.clone())).asAdmin(); // if there is a vertex predicate then there is an implied edge filter on vertices even if there is no // edge predicate provided by the user. if (null == edgeCriterion) - this.edgeCriterion = __.and(inVertexPredicate.asAdmin(), outVertexPredicate.asAdmin()); + this.edgeCriterion = vertexPredicate; else - this.edgeCriterion = edgeCriterion.asAdmin().addStep(new TraversalFilterStep<>(edgeCriterion.asAdmin(), __.and(inVertexPredicate.asAdmin(), outVertexPredicate.asAdmin()))); + this.edgeCriterion = edgeCriterion.asAdmin().addStep(new TraversalFilterStep<>(edgeCriterion.asAdmin(), vertexPredicate)); + } + + if (null != this.vertexCriterion) + this.metadataLabelStartStep(this.vertexCriterion); + if (null != this.edgeCriterion) + this.metadataLabelStartStep(this.edgeCriterion); + } + + private final void metadataLabelStartStep(final Traversal.Admin<?, ?> traversal) { + traversal.getStartStep().addLabel(MARKER); + for (final Step<?, ?> step : traversal.getSteps()) { + if (step instanceof TraversalParent) { + ((TraversalParent) step).getLocalChildren().forEach(this::metadataLabelStartStep); + ((TraversalParent) step).getGlobalChildren().forEach(this::metadataLabelStartStep); + } } } @Override public void apply(final Traversal.Admin<?, ?> traversal) { + // do not apply subgraph strategy to already created subgraph filter branches (or else you get infinite recursion) + if (traversal.getStartStep().getLabels().contains(MARKER)) { + traversal.getStartStep().removeLabel(MARKER); + return; + } + // final List<GraphStep> graphSteps = TraversalHelper.getStepsOfAssignableClass(GraphStep.class, traversal); final List<VertexStep> vertexSteps = TraversalHelper.getStepsOfAssignableClass(VertexStep.class, traversal); - - if (vertexCriterion != null) { + if (null != this.vertexCriterion) { final List<Step> vertexStepsToInsertFilterAfter = new ArrayList<>(); vertexStepsToInsertFilterAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeOtherVertexStep.class, traversal)); vertexStepsToInsertFilterAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeVertexStep.class, traversal)); vertexStepsToInsertFilterAfter.addAll(TraversalHelper.getStepsOfAssignableClass(AddVertexStep.class, traversal)); vertexStepsToInsertFilterAfter.addAll(TraversalHelper.getStepsOfAssignableClass(AddVertexStartStep.class, traversal)); vertexStepsToInsertFilterAfter.addAll(graphSteps.stream().filter(GraphStep::returnsVertex).collect(Collectors.toList())); - - applyCriterion(vertexStepsToInsertFilterAfter, traversal, vertexCriterion.asAdmin()); + applyCriterion(vertexStepsToInsertFilterAfter, traversal, this.vertexCriterion); } - if (edgeCriterion != null) { + if (null != this.edgeCriterion) { final List<Step> edgeStepsToInsertFilterAfter = new ArrayList<>(); edgeStepsToInsertFilterAfter.addAll(TraversalHelper.getStepsOfAssignableClass(AddEdgeStep.class, traversal)); edgeStepsToInsertFilterAfter.addAll(graphSteps.stream().filter(GraphStep::returnsEdge).collect(Collectors.toList())); edgeStepsToInsertFilterAfter.addAll(vertexSteps.stream().filter(VertexStep::returnsEdge).collect(Collectors.toList())); - - applyCriterion(edgeStepsToInsertFilterAfter, traversal, edgeCriterion.asAdmin()); + applyCriterion(edgeStepsToInsertFilterAfter, traversal, this.edgeCriterion); } // explode g.V().out() to g.V().outE().inV() only if there is an edge predicate otherwise - vertexSteps.stream().filter(VertexStep::returnsVertex).forEach(s -> { - if (null == edgeCriterion) - TraversalHelper.insertAfterStep(new TraversalFilterStep<>(traversal, vertexCriterion.asAdmin().clone()), s, traversal); - else { - final VertexStep someEStep = new VertexStep(traversal, Edge.class, s.getDirection(), s.getEdgeLabels()); - final Step someVStep = (s.getDirection() == Direction.BOTH) ? - new EdgeOtherVertexStep(traversal) : new EdgeVertexStep(traversal, s.getDirection().opposite()); - - // if s was labelled then propagate those labels to the new step that will return the vertex - transferLabels(s, someVStep); - - TraversalHelper.replaceStep(s, someEStep, traversal); + vertexSteps.stream().filter(VertexStep::returnsVertex).forEach(step -> { + if (null != this.vertexCriterion && null == edgeCriterion) { + TraversalHelper.insertAfterStep(new TraversalFilterStep<>(traversal, this.vertexCriterion.clone()), step, traversal); + } else { + final VertexStep someEStep = new VertexStep<>(traversal, Edge.class, step.getDirection(), step.getEdgeLabels()); + final Step someVStep = step.getDirection() == Direction.BOTH ? + new EdgeOtherVertexStep(traversal) : + new EdgeVertexStep(traversal, step.getDirection().opposite()); + + // if step was labeled then propagate those labels to the new step that will return the vertex + transferLabels(step, someVStep); + + TraversalHelper.replaceStep(step, someEStep, traversal); TraversalHelper.insertAfterStep(someVStep, someEStep, traversal); - TraversalHelper.insertAfterStep(new TraversalFilterStep<>(traversal, edgeCriterion.asAdmin().clone()), someEStep, traversal); - if (vertexCriterion != null) - TraversalHelper.insertAfterStep(new TraversalFilterStep<>(traversal, vertexCriterion.asAdmin().clone()), someVStep, traversal); + if (null != this.edgeCriterion) + TraversalHelper.insertAfterStep(new TraversalFilterStep<>(traversal, this.edgeCriterion.clone()), someEStep, traversal); + if (null != this.vertexCriterion) + TraversalHelper.insertAfterStep(new TraversalFilterStep<>(traversal, this.vertexCriterion.clone()), someVStep, traversal); } }); } @@ -156,20 +182,36 @@ public final class SubgraphStrategy extends AbstractTraversalStrategy<TraversalS private Builder() { } - public Builder vertexCriterion(final Traversal<Vertex, ?> predicate) { - vertexCriterion = predicate; + public Builder vertices(final Traversal<Vertex, ?> vertexPredicate) { + this.vertexCriterion = vertexPredicate; return this; } - public Builder edgeCriterion(final Traversal<Edge, ?> predicate) { - edgeCriterion = predicate; + public Builder edges(final Traversal<Edge, ?> edgePredicate) { + this.edgeCriterion = edgePredicate; return this; } + @Deprecated + /** + * @deprecated Since 3.2.2, use {@code Builder#vertices} instead. + */ + public Builder vertexCriterion(final Traversal<Vertex, ?> predicate) { + return this.vertices(predicate); + } + + /** + * @deprecated Since 3.2.2, use {@code Builder#edges} instead. + */ + @Deprecated + public Builder edgeCriterion(final Traversal<Edge, ?> predicate) { + return this.edges(predicate); + } + public SubgraphStrategy create() { - if (null == edgeCriterion && null == vertexCriterion) + if (null == this.edgeCriterion && null == this.vertexCriterion) throw new IllegalStateException("A subgraph must be filtered by an edge or vertex criterion"); - return new SubgraphStrategy(vertexCriterion, edgeCriterion); + return new SubgraphStrategy(this.vertexCriterion, this.edgeCriterion); } } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d6a4957/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java index 47a4fbc..86fdb67 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java @@ -18,18 +18,23 @@ */ package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration; +import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep; +import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper; +import org.apache.tinkerpop.gremlin.structure.Vertex; import org.hamcrest.CoreMatchers; import org.junit.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * @author Stephen Mallette (http://stephen.genoprime.com) @@ -71,4 +76,21 @@ public class SubgraphStrategyTest { assertEquals(1, h.getLocalChildren().size()); assertThat(((DefaultGraphTraversal) h.getLocalChildren().get(0)).getEndStep(), CoreMatchers.instanceOf(TraversalFilterStep.class)); } + + @Test + public void shouldNotRetainMetadataLabelMarkers() { + final SubgraphStrategy strategy = SubgraphStrategy.build().vertices(__.<Vertex>out().hasLabel("person")).create(); + final Traversal.Admin<?, ?> t = __.out().inE().asAdmin(); + t.setStrategies(t.getStrategies().clone().addStrategies(strategy)); + t.applyStrategies(); + assertEquals(t.getSteps().get(0).getClass(), VertexStep.class); + assertEquals(t.getSteps().get(1).getClass(), TraversalFilterStep.class); + assertEquals(AndStep.class, ((TraversalFilterStep<?>) t.getSteps().get(1)).getLocalChildren().get(0).getStartStep().getClass()); + assertEquals(0, ((TraversalFilterStep<?>) t.getSteps().get(1)).getLocalChildren().get(0).getStartStep().getLabels().size()); + assertEquals(t.getSteps().get(2).getClass(), EdgeVertexStep.class); + assertEquals(t.getSteps().get(3).getClass(), TraversalFilterStep.class); + assertEquals(VertexStep.class, ((TraversalFilterStep<?>) t.getSteps().get(3)).getLocalChildren().get(0).getStartStep().getClass()); + assertEquals(0, ((TraversalFilterStep<?>) t.getSteps().get(3)).getLocalChildren().get(0).getStartStep().getLabels().size()); + TraversalHelper.getStepsOfAssignableClassRecursively(Step.class, t).forEach(step -> assertTrue(step.getLabels().isEmpty())); + } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d6a4957/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java index 81ea296..41a730a 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyProcessTest.java @@ -22,26 +22,28 @@ import org.apache.tinkerpop.gremlin.LoadGraphWith; import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest; import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner; import org.apache.tinkerpop.gremlin.process.IgnoreEngine; +import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN; +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both; import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE; +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has; +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out; import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.outE; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.hamcrest.core.IsCollectionContaining.hasItems; -import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -54,9 +56,8 @@ public class SubgraphStrategyProcessTest extends AbstractGremlinProcessTest { @Test @LoadGraphWith(MODERN) - @IgnoreEngine(TraversalEngine.Type.COMPUTER) public void shouldFilterVertexCriterion() throws Exception { - final Traversal<Vertex,?> vertexCriterion = __.has("name", P.within("josh", "lop", "ripple")); + final Traversal<Vertex, ?> vertexCriterion = has("name", P.within("josh", "lop", "ripple")); final SubgraphStrategy strategy = SubgraphStrategy.build().vertexCriterion(vertexCriterion).create(); final GraphTraversalSource sg = create(strategy); @@ -139,10 +140,10 @@ public class SubgraphStrategyProcessTest extends AbstractGremlinProcessTest { @Test @LoadGraphWith(MODERN) public void shouldFilterEdgeCriterion() throws Exception { - final Traversal<Edge,?> edgeCriterion = __.or( - __.has("weight", 1.0d).hasLabel("knows"), // 8 - __.has("weight", 0.4d).hasLabel("created").outV().has("name", "marko"), // 9 - __.has("weight", 1.0d).hasLabel("created") // 10 + final Traversal<Edge, ?> edgeCriterion = __.or( + has("weight", 1.0d).hasLabel("knows"), // 8 + has("weight", 0.4d).hasLabel("created").outV().has("name", "marko"), // 9 + has("weight", 1.0d).hasLabel("created") // 10 ); final SubgraphStrategy strategy = SubgraphStrategy.build().edgeCriterion(edgeCriterion).create(); @@ -227,14 +228,30 @@ public class SubgraphStrategyProcessTest extends AbstractGremlinProcessTest { @Test @LoadGraphWith(MODERN) - @IgnoreEngine(TraversalEngine.Type.COMPUTER) + public void shouldFilterComplexVertexCriterion() throws Exception { + checkResults(Arrays.asList("vadas", "josh"), g.withStrategies(SubgraphStrategy.build().vertices(__.<Vertex>in("knows").has("name", "marko")).create()). + V().values("name")); + checkResults(Arrays.asList("vadas", "josh", "lop"), g.withStrategies(SubgraphStrategy.build().vertices(__.<Vertex>in().has("name", "marko")).create()). + V().values("name")); + + checkResults(Arrays.asList("vadas", "josh"), g.withStrategies(SubgraphStrategy.build().vertices(__.<Vertex>in("knows").where(out("created").has("name", "lop"))).create()). + V().values("name")); + checkResults(Arrays.asList("vadas", "josh", "lop"), g.withStrategies(SubgraphStrategy.build().vertices(__.<Vertex>in().where(has("name", "marko").out("created").has("name", "lop"))).create()). + V().values("name")); + + checkResults(Arrays.asList("marko", "vadas", "josh", "lop"), g.withStrategies(SubgraphStrategy.build().vertices(__.or(both().has("name", "marko"), has("name", "marko"))).create()). + V().where(bothE().count().is(P.neq(0))).values("name")); + } + + @Test + @LoadGraphWith(MODERN) public void shouldFilterMixedCriteria() throws Exception { - final Traversal<Vertex,?> vertexCriterion = __.has("name", P.within("josh", "lop", "ripple")); + final Traversal<Vertex, ?> vertexCriterion = has("name", P.within("josh", "lop", "ripple")); // 9 isn't present because marko is not in the vertex list final Traversal<Edge, ?> edgeCriterion = __.or( - __.has("weight", 0.4d).hasLabel("created"), // 11 - __.has("weight", 1.0d).hasLabel("created") // 10 + has("weight", 0.4d).hasLabel("created"), // 11 + has("weight", 1.0d).hasLabel("created") // 10 ); final SubgraphStrategy strategy = SubgraphStrategy.build().edgeCriterion(edgeCriterion).vertexCriterion(vertexCriterion).create(); @@ -309,10 +326,9 @@ public class SubgraphStrategyProcessTest extends AbstractGremlinProcessTest { @Test @LoadGraphWith(MODERN) - @IgnoreEngine(TraversalEngine.Type.COMPUTER) public void shouldFilterVertexCriterionAndKeepLabels() throws Exception { // this will exclude "peter" - final Traversal<Vertex, ?> vertexCriterion = __.has("name", P.within("ripple", "josh", "marko")); + final Traversal<Vertex, ?> vertexCriterion = has("name", P.within("ripple", "josh", "marko")); final SubgraphStrategy strategy = SubgraphStrategy.build().vertexCriterion(vertexCriterion).create(); final GraphTraversalSource sg = create(strategy); @@ -327,7 +343,7 @@ public class SubgraphStrategyProcessTest extends AbstractGremlinProcessTest { @Test(expected = NoSuchElementException.class) @LoadGraphWith(MODERN) public void shouldGetExcludedVertex() throws Exception { - final Traversal<Vertex,?> vertexCriterion = __.has("name", P.within("josh", "lop", "ripple")); + final Traversal<Vertex, ?> vertexCriterion = has("name", P.within("josh", "lop", "ripple")); final SubgraphStrategy strategy = SubgraphStrategy.build().vertexCriterion(vertexCriterion).create(); final GraphTraversalSource sg = create(strategy); @@ -338,10 +354,10 @@ public class SubgraphStrategyProcessTest extends AbstractGremlinProcessTest { @Test(expected = NoSuchElementException.class) @LoadGraphWith(MODERN) public void shouldGetExcludedEdge() throws Exception { - final Traversal<Edge,?> edgeCriterion = __.or( - __.has("weight", 1.0d).hasLabel("knows"), // 8 - __.has("weight", 0.4d).hasLabel("created").outV().has("name", "marko"), // 9 - __.has("weight", 1.0d).hasLabel("created") // 10 + final Traversal<Edge, ?> edgeCriterion = __.or( + has("weight", 1.0d).hasLabel("knows"), // 8 + has("weight", 0.4d).hasLabel("created").outV().has("name", "marko"), // 9 + has("weight", 1.0d).hasLabel("created") // 10 ); final SubgraphStrategy strategy = SubgraphStrategy.build().edgeCriterion(edgeCriterion).create(); @@ -349,7 +365,7 @@ public class SubgraphStrategyProcessTest extends AbstractGremlinProcessTest { sg.E(sg.E(convertToEdgeId("marko", "knows", "vadas")).next()).next(); } - + private GraphTraversalSource create(final SubgraphStrategy strategy) { return graphProvider.traversal(graph, strategy); } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d6a4957/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java ---------------------------------------------------------------------- diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java index 4149ba7..8585e0d 100644 --- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java +++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/interceptor/SparkStarBarrierInterceptor.java @@ -41,6 +41,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet; @@ -158,6 +159,9 @@ public final class SparkStarBarrierInterceptor implements SparkVertexProgramInte public static boolean isLegal(final Traversal.Admin<?, ?> traversal) { final Step<?, ?> startStep = traversal.getStartStep(); final Step<?, ?> endStep = traversal.getEndStep(); + // right now this is not supported because of how the SparkStarBarrierInterceptor mutates the traversal prior to local evaluation + if (traversal.getStrategies().toList().stream().filter(strategy -> strategy instanceof SubgraphStrategy).findAny().isPresent()) + return false; if (!startStep.getClass().equals(GraphStep.class) || ((GraphStep) startStep).returnsEdge()) return false; if (!endStep.getClass().equals(CountGlobalStep.class) &&