Fixed a bug where keepLabels were not being pushed down into child traversals 
by PathRetractionStrategy.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/da762dfe
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/da762dfe
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/da762dfe

Branch: refs/heads/TINKERPOP-1602
Commit: da762dfee9b0ed05fd1185d80403e1be41873b58
Parents: e3889bf
Author: Ted Wilmes <twil...@gmail.com>
Authored: Tue Jan 24 14:57:07 2017 -0600
Committer: Ted Wilmes <twil...@gmail.com>
Committed: Tue Jan 24 14:57:07 2017 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../optimization/PathRetractionStrategy.java    | 58 +++++++++++++++++---
 .../PathRetractionStrategyTest.java             | 19 +++----
 3 files changed, 60 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/da762dfe/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 9453158..95cfb71 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Fixed a bug where `keepLabels` were not being pushed down into child 
traversals by `PathRetractionStrategy`.
 * Fixed a bug associated with user-provided maps and `GroupSideEffectStep`.
 * `GroupBiOperator` no longer maintains a detached traversal and thus, no more 
side-effect related OLAP inconsistencies.
 * Added `ProjectedTraverser` which wraps a traverser with a `List<Object>` of 
projected data.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/da762dfe/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
index fcc22a4..fc7eb8a 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
@@ -24,6 +24,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
 import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
@@ -33,6 +34,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversal
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.PathUtil;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.javatuples.Pair;
 
 import java.util.ArrayList;
@@ -96,8 +98,12 @@ public final class PathRetractionStrategy extends 
AbstractTraversalStrategy<Trav
                 if (currentStep instanceof MatchStep && 
(currentStep.getNextStep().equals(EmptyStep.instance()) || 
currentStep.getNextStep() instanceof DedupGlobalStep)) {
                     pathProcessor.setKeepLabels(((MatchStep) 
currentStep).getMatchStartLabels());
                     pathProcessor.getKeepLabels().addAll(((MatchStep) 
currentStep).getMatchEndLabels());
-                } else
-                    pathProcessor.setKeepLabels(new HashSet<>(keepLabels));
+                } else {
+                    if (pathProcessor.getKeepLabels() == null)
+                        pathProcessor.setKeepLabels(new HashSet<>(keepLabels));
+                    else
+                        pathProcessor.getKeepLabels().addAll(new 
HashSet<>(keepLabels));
+                }
 
                 if (currentStep.getTraversal().getParent() instanceof 
MatchStep) {
                     pathProcessor.setKeepLabels(((MatchStep) 
currentStep.getTraversal().getParent().asStep()).getMatchStartLabels());
@@ -111,6 +117,7 @@ public final class PathRetractionStrategy extends 
AbstractTraversalStrategy<Trav
                         !(currentStep.getNextStep() instanceof Barrier) &&
                         !(currentStep.getTraversal().getParent() instanceof 
MatchStep) &&
                         (!(currentStep.getNextStep() instanceof EmptyStep) || 
TraversalHelper.isGlobalChild(currentStep.getTraversal())))
+
                     TraversalHelper.insertAfterStep(new 
NoOpBarrierStep<>(traversal, this.standardBarrierSize), currentStep, traversal);
             }
         }
@@ -141,16 +148,29 @@ public final class PathRetractionStrategy extends 
AbstractTraversalStrategy<Trav
                 hasRepeat = true;
             }
 
+            // if parent step is a TraversalParent itself and it has more than 
1 child traversal
+            // propagate labels to children
+            if (step instanceof TraversalParent) {
+                final List<Traversal.Admin<Object, Object>> children = new 
ArrayList<>();
+                children.addAll(((TraversalParent) step).getGlobalChildren());
+                children.addAll(((TraversalParent) step).getLocalChildren());
+                // if this is the only child traversal, do not re-push labels
+                if (children.size() > 1)
+                    applyToChildren(keepLabels, children);
+            }
+
             // propagate requirements of keep labels back through the 
traversal's previous steps
             // to ensure that the label is not dropped before it reaches the 
step(s) that require it
             step = step.getPreviousStep();
             while (!(step.equals(EmptyStep.instance()))) {
                 if (step instanceof PathProcessor) {
-                    if (((PathProcessor) step).getKeepLabels() == null) {
-                        ((PathProcessor) step).setKeepLabels(new 
HashSet<>(keepLabels));
-                    } else {
-                        ((PathProcessor) step).getKeepLabels().addAll(new 
HashSet<>(keepLabels));
-                    }
+                    addLabels((PathProcessor) step, keepLabels);
+                }
+                if (step instanceof TraversalParent) {
+                    final List<Traversal.Admin<Object, Object>> children = new 
ArrayList<>();
+                    children.addAll(((TraversalParent) 
step).getGlobalChildren());
+                    children.addAll(((TraversalParent) 
step).getLocalChildren());
+                    applyToChildren(keepLabels, children);
                 }
                 step = step.getPreviousStep();
             }
@@ -190,8 +210,30 @@ public final class PathRetractionStrategy extends 
AbstractTraversalStrategy<Trav
         }
     }
 
+    private void applyToChildren(Set<String> keepLabels, 
List<Traversal.Admin<Object, Object>> children) {
+        for (Traversal.Admin<Object, Object> child : children) {
+            TraversalHelper.applyTraversalRecursively(trav -> addLabels(trav, 
keepLabels), child);
+        }
+    }
+
+    private void addLabels(final Traversal.Admin traversal, final Set<String> 
keepLabels) {
+        for (Object s : traversal.getSteps()) {
+            if (s instanceof PathProcessor) {
+                addLabels((PathProcessor) s, keepLabels);
+            }
+        }
+    }
+
+    private void addLabels(PathProcessor s, Set<String> keepLabels) {
+        if (s.getKeepLabels() == null) {
+            s.setKeepLabels(new HashSet<>(keepLabels));
+        } else {
+            s.getKeepLabels().addAll(new HashSet<>(keepLabels));
+        }
+    }
+
     @Override
     public Set<Class<? extends OptimizationStrategy>> applyPrior() {
         return PRIORS;
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/da762dfe/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
index fc1bc10..71b0ad5 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
@@ -37,14 +37,8 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 
-import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.gte;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
-import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.limit;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
-import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
-import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy.MAX_BARRIER_SIZE;
 import static org.junit.Assert.assertEquals;
 
@@ -153,7 +147,7 @@ public class PathRetractionStrategyTest {
                         as("c").out().as("d", "e").select("c", 
"e").out().select("c"),
                         as("c").out().as("d", "e").select("c", 
"e").out().select("c")).
                         out().select("c"),
-                        "[[b, c, e], [c, e], [[c], [c]], [[c], [c]], []]", 
null},
+                        "[[b, c, e], [c, e], [[c, e], [c, e]], [[c, e], [c, 
e]], []]", null},
                 {__.V().as("a").out().as("b").select("a").select("b").
                         local(as("c").out().as("d", "e").select("c", 
"e").out().select("c")).
                         out().select("c"),
@@ -180,7 +174,12 @@ public class PathRetractionStrategyTest {
                 {__.V().out("created").project("a", 
"b").by("name").by(__.in("created").count()).order().by(select("b")).select("a"),
 "[[[a]], []]", null},
                 {__.order().by("weight", 
Order.decr).store("w").by("weight").filter(values("weight").as("cw").
                         select("w").by(limit(Scope.local, 
1)).as("mw").where("cw", eq("mw"))).project("from", "to", 
"weight").by(__.outV()).by(__.inV()).by("weight"),
-                        "[[[cw, mw], []]]", null}
+                        "[[[cw, mw], []]]", null},
+                
{__.V().limit(1).as("z").out().repeat(store("seen").out().where(without("seen"))).until(where(eq("z"))),
+                        "[[[z, seen]], [[z, seen]]]", null},
+                {__.V().as("a").optional(bothE().dedup().as("b")).
+                        choose(select("b"), select("a","b"), 
project("a").by(select("a"))),
+                        "[[[a, b]], [[a, b]], [[a, b]], [[[a, b]]], [[a, 
b]]]", null}
         });
     }
 }

Reply via email to