This is an automated email from the ASF dual-hosted git repository. colegreer pushed a commit to branch repeatLimit in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 969c9abab81e142a0346daa118f666cd1b66125a Author: Andrea Child <[email protected]> AuthorDate: Fri Aug 29 22:14:35 2025 -0700 Handle scenario where repeat contains out.limit. --- .../process/traversal/step/branch/RepeatStep.java | 23 +++++++++++++++++++++- .../traversal/step/filter/RangeGlobalStep.java | 10 +++++++--- .../traverser/B_LP_NL_O_S_SE_SL_Traverser.java | 1 + .../traverser/LP_NL_O_OB_P_S_SE_SL_Traverser.java | 1 + .../traverser/LP_NL_O_OB_S_SE_SL_Traverser.java | 1 + .../traverser/NL_O_OB_S_SE_SL_Traverser.java | 1 + .../tinkergraph/structure/TinkerGraphPlayTest.java | 15 ++++++++++++++ 7 files changed, 48 insertions(+), 4 deletions(-) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java index b37d51ab3c..2aa7ca9355 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java @@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareSte import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil; +import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; @@ -235,9 +236,13 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav while (true) { if (this.repeatTraversal.getEndStep().hasNext()) { - return this.repeatTraversal.getEndStep(); + Traverser.Admin<S> result = this.repeatTraversal.getEndStep().next(); + System.out.printf("RepeatStep returning result: %s Path: %s%n", + ((Vertex) result.get()).property("id").value(), result.path()); + return IteratorUtils.of(result); } else { final Traverser.Admin<S> start = this.starts.next(); + String ln; if (this.loopName != null) { ln = this.getId(); @@ -246,11 +251,19 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav } start.initialiseLoops(this.getId(), ln); + System.out.printf("RepeatStep processing start: %s Path: %s Loops: %d%n", + ((Vertex) start.get()).property("id").value(), start.path(), start.loops()); if (doUntil(start, true)) { + System.out.printf("RepeatStep until condition met, exiting: %s%n", + ((Vertex) start.get()).property("id").value()); start.resetLoops(); return IteratorUtils.of(start); } + + System.out.printf("RepeatStep adding to repeat traversal: %s%n", + ((Vertex) start.get()).property("id").value()); this.repeatTraversal.addStart(start); + if (doEmit(start, true)) { final Traverser.Admin<S> emitSplit = start.split(); emitSplit.resetLoops(); @@ -342,11 +355,19 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav final RepeatStep<S> repeatStep = (RepeatStep<S>) this.getTraversal().getParent(); while (true) { final Traverser.Admin<S> start = this.starts.next(); + System.out.printf("RepeatEndStep processing: %s Path: %s Loops: %d%n", + ((Vertex) start.get()).property("id").value(), start.path(), start.loops()); start.incrLoops(); + System.out.printf("RepeatEndStep after incrLoops: %s Loops: %d%n", + ((Vertex) start.get()).property("id").value(), start.loops()); if (repeatStep.doUntil(start, false)) { + System.out.printf("RepeatEndStep until condition met, resetting loops: %s%n", + ((Vertex) start.get()).property("id").value()); start.resetLoops(); return IteratorUtils.of(start); } else { + System.out.printf("RepeatEndStep continuing repeat: %s%n", + ((Vertex) start.get()).property("id").value()); if (!repeatStep.untilFirst && !repeatStep.emitFirst) repeatStep.repeatTraversal.addStart(start); else diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java index 2b7c7431c7..07dd40e277 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java @@ -82,11 +82,15 @@ public final class RangeGlobalStep<S> extends FilterStep<S> implements Ranging, // TODO: account scenario where parent is not repeat step? Step<?, ?> ps = pt.asStep(); String pid = ps.getId(); + int loops = traverser.loops(pid); + System.out.printf("Parent: %s PID: %s Loops: %d TraverserLoops: %d%n", ps, pid, loops, traverser.loops()); sb.append(pid).append(":"); - sb.append(traverser.loops(pid)).append(":"); + sb.append(loops).append(":"); t = ps.getTraversal(); } sb.append(this.getId()).append(":").append(traverser.loops()); +// Object pathHead = traverser.path().get(0); +// sb.append(":").append(pathHead.toString()); // Create counter key that isolates between different repeat step contexts String iterationKey = sb.toString(); @@ -96,8 +100,8 @@ public final class RangeGlobalStep<S> extends FilterStep<S> implements Ranging, } if (this.high != -1 && currentCounter.get() >= this.high) { - System.out.printf("FastNoSuchElementException for Traverser: %s Counter: %d%n", traverser.path(), currentCounter.get()); - throw FastNoSuchElementException.instance(); + System.out.printf("Filtering out traverser (reached high limit): %s Counter: %d%n", traverser.path(), currentCounter.get()); + return false; } long avail = traverser.bulk(); 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 401bfd279a..1d30928564 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 @@ -62,6 +62,7 @@ public class B_LP_NL_O_S_SE_SL_Traverser<T> extends B_LP_O_S_SE_SL_Traverser<T> if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) { final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0); this.nestedLoops.push(lc); + this.loopNames.put(stepLabel, lc); if (loopName != null) this.loopNames.put(loopName, lc); } 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 77157b8a22..595c1b923d 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 @@ -63,6 +63,7 @@ public class LP_NL_O_OB_P_S_SE_SL_Traverser<T> extends LP_O_OB_P_S_SE_SL_Travers if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) { final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0); this.nestedLoops.push(lc); + this.loopNames.put(stepLabel, lc); if (loopName != null) this.loopNames.put(loopName, lc); } 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 14c2fe379a..3b61be4b47 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 @@ -68,6 +68,7 @@ public class LP_NL_O_OB_S_SE_SL_Traverser<T> extends LP_O_OB_S_SE_SL_Traverser<T if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) { final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0); this.nestedLoops.push(lc); + this.loopNames.put(stepLabel, lc); if (loopName != null) this.loopNames.put(loopName, lc); } 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 c30e893308..3040784706 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 @@ -63,6 +63,7 @@ public class NL_O_OB_S_SE_SL_Traverser<T> extends O_OB_S_SE_SL_Traverser<T> { if (this.nestedLoops.empty() || !this.nestedLoops.peek().hasLabel(stepLabel)) { final LabelledCounter lc = new LabelledCounter(stepLabel, (short) 0); this.nestedLoops.push(lc); + this.loopNames.put(stepLabel, lc); if (loopName != null) this.loopNames.put(loopName, lc); } diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java index af6485be9e..c9317ba083 100644 --- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java +++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java @@ -59,6 +59,7 @@ import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.union; import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.valueMap; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * @author Stephen Mallette (http://stephen.genoprime.com); @@ -95,6 +96,20 @@ public class TinkerGraphPlayTest { .limit(2).out("knows") .path().by("id"); assertEquals(toListAndPrint("basic", basic), toListAndPrint("basicUnfolded", basicUnfolded)); + + } + + @Test + public void testRepeatOutLimit() { + GraphTraversal<Vertex, Path> basic = g.V().has("id", "l2-0") + .repeat(__.out("knows").limit(2)) + .times(2).path().by("id"); + GraphTraversal<Vertex, Path> basicUnfolded = g.V().has("id", "l2-0") + .out("knows").limit(2) + .out("knows").limit(2) + .path().by("id"); + assertEquals(toListAndPrint("basic", basic), toListAndPrint("basicUnfolded", basicUnfolded)); + } @Test
