You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2025/07/24 20:34:54 UTC

(tinkerpop) branch TINKERPOP-3178 created (now 8217a12913)

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a change to branch TINKERPOP-3178
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


      at 8217a12913 wip

This branch includes the following new commits:

     new c0848a2cb3 TINKERPOP-3178 Match on a single case in choose step
     new 8217a12913 wip

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(tinkerpop) 02/02: wip

Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-3178
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 8217a12913a656a83c79ca27eda77fc572b7c279
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Thu Jul 24 16:34:24 2025 -0400

    wip
---
 .../gremlin/test/features/branch/Choose.feature    | 72 ++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
index 6f810d6563..9ba4f40674 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
@@ -187,3 +187,75 @@ Feature: Step - choose()
       | vadas |
       | josh |
       | peter |
+
+  Scenario: g_V_chooseXhasLabelXpersonX_localXchooseXageX_optionXbetweenX26_30X_name_foldX_optionXnone_name_foldXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().hasLabel("person").
+        local(choose(__.values("age")).
+                option(P.between(26, 30), __.values("name").fold()).
+                option(Pick.none, __.values("name").fold()))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | l[marko] |
+      | l[vadas] |
+      | l[josh] |
+      | l[peter] |
+
+  Scenario: g_V_chooseXhasLabelXpersonX_mapXchooseXageX_optionXbetweenX26_30X_name_foldX_optionXnone_name_foldXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().hasLabel("person").
+        map(choose(__.values("age")).
+              option(P.between(26, 30), __.values("name").fold()).
+              option(Pick.none, __.values("name").fold()))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | l[marko] |
+      | l[vadas] |
+      | l[josh] |
+      | l[peter] |
+
+  Scenario: g_unionXV_VXhasLabelXpersonX_barrier_localXchooseXageX_optionXbetweenX26_30X_name_foldX_optionXnone_name_foldXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.union(__.V(), __.V()).hasLabel("person").barrier().
+        local(choose(__.values("age")).
+                option(P.between(26, 30), __.values("name").fold()).
+                option(Pick.none, __.values("name").fold()))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | l[marko, marko] |
+      | l[vadas, vadas] |
+      | l[josh, josh] |
+      | l[peter, peter] |
+
+  Scenario: g_unionXV_VXhasLabelXpersonX_barrier_mapXchooseXageX_optionXbetweenX26_30X_name_foldX_optionXnone_name_foldXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.union(__.V(), __.V()).hasLabel("person").barrier().
+        map(choose(__.values("age")).
+              option(P.between(26, 30), __.values("name").fold()).
+              option(Pick.none, __.values("name").fold()))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | l[marko] |
+      | l[marko] |
+      | l[vadas] |
+      | l[vadas] |
+      | l[josh] |
+      | l[josh] |
+      | l[peter] |
+      | l[peter] |
\ No newline at end of file


(tinkerpop) 01/02: TINKERPOP-3178 Match on a single case in choose step

Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-3178
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit c0848a2cb3365703570b86da232da02c4a102753
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Wed Jul 23 15:46:20 2025 -0400

    TINKERPOP-3178 Match on a single case in choose step
---
 .../process/traversal/step/branch/BranchStep.java  |  6 ++--
 .../process/traversal/step/branch/ChooseStep.java  | 13 ++++++++
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  2 ++
 gremlin-go/driver/cucumber/gremlin.go              |  2 ++
 .../gremlin-javascript/test/cucumber/gremlin.js    |  2 ++
 gremlin-python/src/main/python/radish/gremlin.py   |  2 ++
 .../gremlin/test/features/branch/Choose.feature    | 35 ++++++++++++++++++++++
 7 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
index fa5956d1b9..c743e0b028 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
@@ -53,7 +53,7 @@ public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements Trav
     protected List<Pair<Traversal.Admin<M, ?>, Traversal.Admin<S, E>>> traversalOptions = new ArrayList<>();
 
     private boolean first = true;
-    private boolean hasBarrier;
+    protected boolean hasBarrier;
 
     public BranchStep(final Traversal.Admin traversal) {
         super(traversal);
@@ -142,7 +142,7 @@ public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements Trav
     /**
      * Choose the right traversal option to apply and seed those options with this traverser.
      */
-    private void applyCurrentTraverser(final Traverser.Admin<S> start) {
+    protected void applyCurrentTraverser(final Traverser.Admin<S> start) {
         // first get the value of the choice based on the current traverser and use that to select the right traversal
         // option to which that traverser should be routed
         final M choice = TraversalUtil.apply(start, this.branchTraversal);
@@ -188,7 +188,7 @@ public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements Trav
         return ends.iterator();
     }
 
-    private List<Traversal.Admin<S, E>> pickBranches(final M choice) {
+    protected List<Traversal.Admin<S, E>> pickBranches(final M choice) {
         final List<Traversal.Admin<S, E>> branches = new ArrayList<>();
         if (choice instanceof Pick) {
             if (this.traversalPickOptions.containsKey(choice)) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
index 86ec39e145..e8c44153f5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
@@ -20,7 +20,14 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.branch;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Pick;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.HasNextStep;
+import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
 
 /**
  * A step which offers a choice of two or more Traversals to take.
@@ -51,4 +58,10 @@ public final class ChooseStep<S, E, M> extends BranchStep<S, E, M> {
         }
         super.addChildOption(pickToken, traversalOption);
     }
+
+    @Override
+    protected List<Traversal.Admin<S, E>> pickBranches(final M choice) {
+        final List<Traversal.Admin<S, E>> branches = super.pickBranches(choice);
+        return branches != null ? branches.subList(0, 1) : null;
+    }
 }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 5908c0d966..a2b97772c0 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -75,6 +75,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_hasLabelXpersonX_chooseXageX__optionX27L__constantXyoungXX_optionXnone__constantXoldXX_groupCount", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Choose<object>(__.Values<object>("age")).Option(p["xx1"], __.Constant<object>("young")).Option(Pick.None, __.Constant<object>("old")).GroupCount<object>()}}, 
                {"g_injectX1X_chooseXisX1X__constantX10Xfold__foldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx2"]).Choose<object>(__.Is(p["xx2"]), __.Constant<object>(p["xx1"]).Fold(), __.Fold<object>())}}, 
                {"g_injectX2X_chooseXisX1X__constantX10Xfold__foldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx3"]).Choose<object>(__.Is(p["xx2"]), __.Constant<object>(p["xx1"]).Fold(), __.Fold<object>())}}, 
+               {"g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_constantXxXX_optionXbetweenX20_30X_constantXzXX_optionXnone_constantXzXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Choose<object>(__.Values<object>("age")).Option(P.Between(26, 30), __.Constant<object>("x")).Option(P.Between(20, 30), __.Constant<object>("y")).Option(Pick.None, __.Constant<object>("z"))}}, 
+               {"g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_nameX_optionXnone_nameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Choose<object>(__.Values<object>("age")).Option(P.Between(26, 30), __.Values<object>("name")).Option(Pick.None, __.Values<object>("name"))}}, 
                {"g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.Properties<object>("location").Order().By(T.Value, Order.Asc).Range<object>(0, 2)).Value<object>()}}, 
                {"g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has(T.Label, "person").As("a").Local<object>(__.Out("created").As("b")).Select<object>("a", "b").By("name").By(T.Id)}}, 
                {"g_V_localXoutE_countX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.OutE().Count())}}, 
diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index 1574cb18df..07b3f64f7e 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -45,6 +45,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
     "g_V_hasLabelXpersonX_chooseXageX__optionX27L__constantXyoungXX_optionXnone__constantXoldXX_groupCount": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Choose(gremlingo.T__.Values("age")).Option(p["xx1"], gremlingo.T__.Constant("young")).Option(gremlingo.Pick.None, gremlingo.T__.Constant("old")).GroupCount()}}, 
     "g_injectX1X_chooseXisX1X__constantX10Xfold__foldX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx2"]).Choose(gremlingo.T__.Is(p["xx2"]), gremlingo.T__.Constant(p["xx1"]).Fold(), gremlingo.T__.Fold())}}, 
     "g_injectX2X_chooseXisX1X__constantX10Xfold__foldX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx3"]).Choose(gremlingo.T__.Is(p["xx2"]), gremlingo.T__.Constant(p["xx1"]).Fold(), gremlingo.T__.Fold())}}, 
+    "g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_constantXxXX_optionXbetweenX20_30X_constantXzXX_optionXnone_constantXzXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Choose(gremlingo.T__.Values("age")).Option(gremlingo.P.Between(26, 30), gremlingo.T__.Constant("x")).Option(gremlingo.P.Between(20, 30), gremlingo.T__.Constant("y")).Option(gremlingo.Pick.None, gremlingo.T__.Constant("z"))}}, 
+    "g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_nameX_optionXnone_nameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Choose(gremlingo.T__.Values("age")).Option(gremlingo.P.Between(26, 30), gremlingo.T__.Values("name")).Option(gremlingo.Pick.None, gremlingo.T__.Values("name"))}}, 
     "g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Local(gremlingo.T__.Properties("location").Order().By(gremlingo.T.Value, gremlingo.Order.Asc).Range(0, 2)).Value()}}, 
     "g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, "person").As("a").Local(gremlingo.T__.Out("created").As("b")).Select("a", "b").By("name").By(gremlingo.T.Id)}}, 
     "g_V_localXoutE_countX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Local(gremlingo.T__.OutE().Count())}}, 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index aab974e253..bb99c73e56 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -75,6 +75,8 @@ const gremlins = {
     g_V_hasLabelXpersonX_chooseXageX__optionX27L__constantXyoungXX_optionXnone__constantXoldXX_groupCount: [function({g, xx1}) { return g.V().hasLabel("person").choose(__.values("age")).option(xx1, __.constant("young")).option(Pick.none, __.constant("old")).groupCount() }], 
     g_injectX1X_chooseXisX1X__constantX10Xfold__foldX: [function({g, xx1, xx2}) { return g.inject(xx2).choose(__.is(xx2), __.constant(xx1).fold(), __.fold()) }], 
     g_injectX2X_chooseXisX1X__constantX10Xfold__foldX: [function({g, xx1, xx3, xx2}) { return g.inject(xx3).choose(__.is(xx2), __.constant(xx1).fold(), __.fold()) }], 
+    g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_constantXxXX_optionXbetweenX20_30X_constantXzXX_optionXnone_constantXzXX: [function({g}) { return g.V().hasLabel("person").choose(__.values("age")).option(P.between(26, 30), __.constant("x")).option(P.between(20, 30), __.constant("y")).option(Pick.none, __.constant("z")) }], 
+    g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_nameX_optionXnone_nameX: [function({g}) { return g.V().hasLabel("person").choose(__.values("age")).option(P.between(26, 30), __.values("name")).option(Pick.none, __.values("name")) }], 
     g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value: [function({g}) { return g.V().local(__.properties("location").order().by(T.value, Order.asc).range(0, 2)).value() }], 
     g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX: [function({g}) { return g.V().has(T.label, "person").as("a").local(__.out("created").as("b")).select("a", "b").by("name").by(T.id) }], 
     g_V_localXoutE_countX: [function({g}) { return g.V().local(__.outE().count()) }], 
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 27a45da568..3616d5a8e6 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -48,6 +48,8 @@ world.gremlins = {
     'g_V_hasLabelXpersonX_chooseXageX__optionX27L__constantXyoungXX_optionXnone__constantXoldXX_groupCount': [(lambda g, xx1=None:g.V().has_label('person').choose(__.values('age')).option(xx1, __.constant('young')).option(Pick.none, __.constant('old')).group_count())], 
     'g_injectX1X_chooseXisX1X__constantX10Xfold__foldX': [(lambda g, xx1=None,xx2=None:g.inject(xx2).choose(__.is_(xx2), __.constant(xx1).fold(), __.fold()))], 
     'g_injectX2X_chooseXisX1X__constantX10Xfold__foldX': [(lambda g, xx1=None,xx3=None,xx2=None:g.inject(xx3).choose(__.is_(xx2), __.constant(xx1).fold(), __.fold()))], 
+    'g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_constantXxXX_optionXbetweenX20_30X_constantXzXX_optionXnone_constantXzXX': [(lambda g:g.V().has_label('person').choose(__.values('age')).option(P.between(26, 30), __.constant('x')).option(P.between(20, 30), __.constant('y')).option(Pick.none, __.constant('z')))], 
+    'g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_nameX_optionXnone_nameX': [(lambda g:g.V().has_label('person').choose(__.values('age')).option(P.between(26, 30), __.values('name')).option(Pick.none, __.values('name')))], 
     'g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value': [(lambda g:g.V().local(__.properties('location').order().by(T.value, Order.asc).range_(0, 2)).value())], 
     'g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX': [(lambda g:g.V().has(T.label, 'person').as_('a').local(__.out('created').as_('b')).select('a', 'b').by('name').by(T.id_))], 
     'g_V_localXoutE_countX': [(lambda g:g.V().local(__.out_e().count()))], 
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
index 9067922b23..6f810d6563 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
@@ -152,3 +152,38 @@ Feature: Step - choose()
     Then the result should be unordered
       | result |
       | l[d[2].i] |
+
+  Scenario: g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_constantXxXX_optionXbetweenX20_30X_constantXzXX_optionXnone_constantXzXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().hasLabel("person").
+        choose(__.values("age")).
+          option(P.between(26, 30), __.constant("x")).
+          option(P.between(20, 30), __.constant("y")).
+          option(Pick.none, __.constant("z"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | x |
+      | x |
+      | z |
+      | z |
+
+  Scenario: g_V_chooseXhasLabelXpersonX_chooseXageX_optionXbetweenX26_30X_nameX_optionXnone_nameX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().hasLabel("person").
+        choose(__.values("age")).
+          option(P.between(26, 30), __.values("name")).
+          option(Pick.none, __.values("name"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | marko |
+      | vadas |
+      | josh |
+      | peter |