Correction to Nested Loop Traverser split function Added clone() method to LabelledCounter implementing the Cloneable interface. Deep clone the loop stack when spliting a Nested Loop Traverer. Added test which fails without this fix.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/3974b071 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/3974b071 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/3974b071 Branch: refs/heads/TINKERPOP-1996 Commit: 3974b071d595b2f98b0d8e7080b1c5cbf6221949 Parents: ad35a6a Author: GCHQResearcher1337 <[email protected]> Authored: Thu Jun 28 09:11:49 2018 +0100 Committer: GCHQResearcher1337 <[email protected]> Committed: Sat Jun 30 09:44:43 2018 +0100 ---------------------------------------------------------------------- .../B_LP_NL_O_P_S_SE_SL_Traverser.java | 8 +++++-- .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java | 8 +++++-- .../traverser/B_NL_O_S_SE_SL_Traverser.java | 8 +++++-- .../LP_NL_O_OB_P_S_SE_SL_Traverser.java | 8 +++++-- .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java | 8 +++++-- .../traverser/NL_O_OB_S_SE_SL_Traverser.java | 8 +++++-- .../traverser/util/LabelledCounter.java | 7 +++++- gremlin-test/features/branch/Repeat.feature | 14 ++++++++++++ .../traversal/step/branch/RepeatTest.java | 23 ++++++++++++++++++++ 9 files changed, 79 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java index c45e9a8..b837642 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_P_S_SE_SL_Traverser.java @@ -66,14 +66,18 @@ public class B_LP_NL_O_P_S_SE_SL_Traverser<T> extends B_LP_O_P_S_SE_SL_Traverser @Override public <R> Admin<R> split(final R r, final Step<T, R> step) { final B_LP_NL_O_P_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<R>) super.split(r, step); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } @Override public Admin<T> split() { final B_LP_NL_O_P_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_P_S_SE_SL_Traverser<T>) super.split(); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java index 3959dd7..a4bc1bd 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_NL_O_S_SE_SL_Traverser.java @@ -66,14 +66,18 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T> @Override public <R> Admin<R> split(final R r, final Step<T, R> step) { final B_LP_NL_O_S_SE_SL_Traverser<R> clone = (B_LP_NL_O_S_SE_SL_Traverser<R>) super.split(r, step); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } @Override public Admin<T> split() { final B_LP_NL_O_S_SE_SL_Traverser<T> clone = (B_LP_NL_O_S_SE_SL_Traverser<T>) super.split(); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java index 11ce7fa..369448e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_NL_O_S_SE_SL_Traverser.java @@ -66,14 +66,18 @@ public class B_NL_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> { @Override public <R> Admin<R> split(final R r, final Step<T, R> step) { final B_NL_O_S_SE_SL_Traverser<R> clone = (B_NL_O_S_SE_SL_Traverser<R>) super.split(r, step); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } @Override public Admin<T> split() { final B_NL_O_S_SE_SL_Traverser<T> clone = (B_NL_O_S_SE_SL_Traverser<T>) super.split(); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java index f8b814f..2409e4a 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java @@ -67,14 +67,18 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers @Override public <R> Admin<R> split(final R r, final Step<T, R> step) { final LP_NL_O_OB_P_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<R>) super.split(r, step); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } @Override public Admin<T> split() { final LP_NL_O_OB_P_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_P_S_SE_SL_Traverser<T>) super.split(); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java index 9649f80..65fda97 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/LP_NL_O_OB_S_SE_SL_Traverser.java @@ -67,14 +67,18 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T @Override public <R> Admin<R> split(final R r, final Step<T, R> step) { final LP_NL_O_OB_S_SE_SL_Traverser<R> clone = (LP_NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } @Override public Admin<T> split() { final LP_NL_O_OB_S_SE_SL_Traverser<T> clone = (LP_NL_O_OB_S_SE_SL_Traverser<T>) super.split(); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java index 2734d51..3975758 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/NL_O_OB_S_SE_SL_Traverser.java @@ -67,14 +67,18 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> { @Override public <R> Admin<R> split(final R r, final Step<T, R> step) { final NL_O_OB_S_SE_SL_Traverser<R> clone = (NL_O_OB_S_SE_SL_Traverser<R>) super.split(r, step); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } @Override public Admin<T> split() { final NL_O_OB_S_SE_SL_Traverser<T> clone = (NL_O_OB_S_SE_SL_Traverser<T>) super.split(); - clone.nestedLoops = (Stack<LabelledCounter>)this.nestedLoops.clone(); + clone.nestedLoops = new Stack<>(); + for(LabelledCounter lc : this.nestedLoops) + clone.nestedLoops.add((LabelledCounter) lc.clone()); return clone; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java index fe76891..a5214d2 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/LabelledCounter.java @@ -26,7 +26,7 @@ import java.io.Serializable; /** * Class to track a count associated with a Label */ -public class LabelledCounter implements Serializable { +public class LabelledCounter implements Serializable, Cloneable { private final String label; @@ -53,6 +53,11 @@ public class LabelledCounter implements Serializable { } @Override + public Object clone() { + return new LabelledCounter(this.label, this.count.shortValue()); + } + + @Override public boolean equals(final Object o) { if (this == o) return true; if (!(o instanceof LabelledCounter)) return false; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-test/features/branch/Repeat.feature ---------------------------------------------------------------------- diff --git a/gremlin-test/features/branch/Repeat.feature b/gremlin-test/features/branch/Repeat.feature index b176477..c38fa1b 100644 --- a/gremlin-test/features/branch/Repeat.feature +++ b/gremlin-test/features/branch/Repeat.feature @@ -292,3 +292,17 @@ Scenario: g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_r | result | | java | | java | + +Scenario: g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values + Given the modern graph + And using the parameter v3Id defined as "v[lop].id" + And the traversal of + """ + g.V(v3Id).repeat(__.both("created")).until(__.loops().is(40)).emit(__.repeat(__.in("knows")).emit(__.loops().is(1))).dedup().values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | josh | + | lop | + | ripple | http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3974b071/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java index d8da3fb..80c9332 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatTest.java @@ -109,6 +109,8 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest { public abstract Traversal<Vertex, String> get_g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang(); + public abstract Traversal<Vertex, String> get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(final Object v3Id); + @Test @LoadGraphWith(MODERN) public void g_V_repeatXoutX_timesX2X_emit_path() { @@ -379,6 +381,22 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest { assertFalse(traversal.hasNext()); } + @Test + @LoadGraphWith(MODERN) + public void g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values() { + final Traversal<Vertex, String> traversal = get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(convertToVertexId("lop")); + + printTraversalForm(traversal); + for (String res : new String[]{"josh","lop", "ripple"}) + { + assertTrue(traversal.hasNext()); + String lang = traversal.next(); + assertEquals(lang, res); + } + + assertFalse(traversal.hasNext()); + } + public static class Traversals extends RepeatTest { @@ -477,5 +495,10 @@ public abstract class RepeatTest extends AbstractGremlinProcessTest { public Traversal<Vertex, String> get_g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang() { return g.V().until(__.constant(true)).repeat(__.repeat(out("created")).until(__.has("name", "ripple"))).emit().values("lang"); } + + @Override + public Traversal<Vertex, String> get_g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values(final Object v3Id) { + return g.V(v3Id).repeat( __.both("created")).until(loops().is(40)).emit(__.repeat(__.in("knows")).emit(loops().is(1))).dedup().values("name"); + } } }
