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 2023/10/13 16:13:12 UTC
[tinkerpop] branch master updated: TINKERPOP-3000 Fixed bug in union() start
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/master by this push:
new 7be80b3082 TINKERPOP-3000 Fixed bug in union() start
7be80b3082 is described below
commit 7be80b3082303124a682f56ff0272eb23ffa85a2
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Oct 13 12:12:13 2023 -0400
TINKERPOP-3000 Fixed bug in union() start
Path history should start with the child traversals to union() CTR
---
.../process/traversal/step/branch/UnionStep.java | 36 ++++++++-
.../traverser/B_LP_O_P_S_SE_SL_Traverser.java | 5 ++
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 6 +-
gremlin-go/driver/cucumber/gremlin.go | 6 +-
.../gremlin-javascript/test/cucumber/gremlin.js | 6 +-
gremlin-python/src/main/python/radish/gremlin.py | 6 +-
.../gremlin/test/features/branch/Union.feature | 91 +++++++++++++++++-----
7 files changed, 132 insertions(+), 24 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
index 96060821c8..eb4a32c9d8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
@@ -34,9 +34,21 @@ import java.util.Iterator;
*/
public class UnionStep<S, E> extends BranchStep<S, E, Pick> {
+ /**
+ * Determines if this step is configured to be used as a start step.
+ */
private final boolean isStart;
+
+ /**
+ * Is this the first iteration through the step.
+ */
protected boolean first = true;
+ /**
+ * A placeholder object used to kick off the first traverser in the union.
+ */
+ static final Object UNION_STARTER = new Object();
+
public UnionStep(final Traversal.Admin traversal, final boolean isStart, final Traversal.Admin<?, E>... unionTraversals) {
super(traversal);
this.isStart = isStart;
@@ -50,15 +62,35 @@ public class UnionStep<S, E> extends BranchStep<S, E, Pick> {
this(traversal, false, unionTraversals);
}
+ public boolean isStart() {
+ return isStart;
+ }
+
@Override
protected Traverser.Admin<E> processNextStart() {
// when it's a start step a traverser needs to be created to kick off the traversal.
if (isStart && first) {
first = false;
final TraverserGenerator generator = this.getTraversal().getTraverserGenerator();
- this.addStart(generator.generate(false, (Step) this, 1L));
+ final Traverser.Admin<S> traverser = generator.generate(UNION_STARTER, (Step) this, 1L);
+
+ // immediately drop the path which would include "false" otherwise. let the path start with the
+ // traversers produced from the children to the union()
+ traverser.dropPath();
+ this.addStart(traverser);
+ }
+
+ // if this isStart then loop through the next starts until we find one that doesn't hold the
+ // UNION_STARTER and return that. this deals with inject() which is always a start step even
+ // when used mid-traversal.
+ Traverser.Admin<E> t = super.processNextStart();
+ if (isStart) {
+ while (t != null && t.get() == UNION_STARTER) {
+ t = super.processNextStart();
+ }
}
- return super.processNextStart();
+
+ return t;
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
index 7e603dc44c..ae9fef3d6a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
@@ -73,6 +73,11 @@ public class B_LP_O_P_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
return clone;
}
+ @Override
+ public void dropPath() {
+ path = ImmutablePath.make();
+ }
+
@Override
public void addLabels(final Set<String> labels) {
this.path = this.path.extend(labels);
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index c61ad4a975..a763f02f91 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -117,10 +117,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat("a",__.Out("knows").Repeat("b",__.Out("created").Filter(__.Loops("a").Is(0))).Emit()).Emit().Values<object>("lang")}},
{"g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid6"]).Repeat("a",__.Both("created").SimplePath()).Emit(__.Repeat("b",__.Both("knows")).Until(__.Loops("b").As("b").Where(__.Loops("a").As("b"))).Has("name","vadas")).Dedup().Values<object>("name")}},
{"g_unionXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>()}},
- {"g_unionXconstantX1X_constantX2X_constantX3XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.Constant<object>(p["xx1"]),__.Constant<object>(p["xx2"]),__.Constant<object>(p["xx3"]))}},
{"g_unionXV_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.V().Values<object>("name"))}},
{"g_unionXVXv1X_VX4XX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.V((Vertex) p["v1"]),__.V((Vertex) p["v4"])).Values<object>("name")}},
{"g_unionXV_hasLabelXsoftwareX_V_hasLabelXpersonXX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.V().HasLabel("software"),__.V().HasLabel("person")).Values<object>("name")}},
+ {"g_unionXV_out_out_V_hasLabelXsoftwareXX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.V().Out().Out(),__.V().HasLabel("software")).Path()}},
+ {"g_unionXV_out_out_V_hasLabelXsoftwareXX_path_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.V().Out().Out(),__.V().HasLabel("software")).Path().By("name")}},
+ {"g_unionXunionXV_out_outX_V_hasLabelXsoftwareXX_path_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.Union<object>(__.V().Out().Out()),__.V().HasLabel("software")).Path().By("name")}},
+ {"g_unionXinjectX1X_injectX2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.Inject(1),__.Inject(2))}},
{"g_V_unionXconstantX1X_constantX2X_constantX3XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v2"]).Union<object>(__.Constant<object>(p["xx1"]),__.Constant<object>(p["xx2"]),__.Constant<object>(p["xx3"]))}},
{"g_V_unionXout__inX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Union<object>(__.Out(),__.In()).Values<object>("name")}},
{"g_VX1X_unionXrepeatXoutX_timesX2X__outX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Union<object>(__.Repeat(__.Out()).Times(2),__.Out()).Values<object>("name")}},
@@ -130,6 +133,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_VX1_2X_unionXoutE_count__inE_count__outE_weight_sumX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"],p["vid2"]).Union<object>(__.OutE().Count(),__.InE().Count(),__.OutE().Values<object>("weight").Sum<object>())}},
{"g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"],p["vid2"]).Local<object>(__.Union<object>(__.OutE().Count(),__.InE().Count(),__.OutE().Values<object>("weight").Sum<object>()))}},
{"g_VX1_2X_localXunionXcountXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"],p["vid2"]).Local<object>(__.Union<object>(__.Count()))}},
+ {"g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Union<object>(__.AddV("person").Property("name","alice"),__.AddV("person").Property("name","bob"),__.AddV("person").Property("name","chris")).Values<object>("name")}},
{"g_V_valuesXageX_allXgtX32XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").All(P.Gt(32))}},
{"g_V_valuesXageX_whereXisXP_gtX33XXX_fold_allXgtX33XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Where(__.Is(P.Gt(33))).Fold().All(P.Gt(33))}},
{"g_V_valuesXageX_order_byXdescX_fold_allXgtX10XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Order().By(Order.Desc).Fold().All(P.Gt(10))}},
diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index e2f3134328..458abafba2 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -88,10 +88,13 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Repeat("a", gremlingo.T__.Out("knows").Repeat("b", gremlingo.T__.Out("created").Filter(gremlingo.T__.Loops("a").Is(0))).Emit()).Emit().Values("lang")}},
"g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid6"]).Repeat("a", gremlingo.T__.Both("created").SimplePath()).Emit(gremlingo.T__.Repeat("b", gremlingo.T__.Both("knows")).Until(gremlingo.T__.Loops("b").As("b").Where(gremlingo.T__.Loops("a").As("b"))).Has("name", "vadas")).Dedup().Value [...]
"g_unionXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union()}},
- "g_unionXconstantX1X_constantX2X_constantX3XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.Constant(p["xx1"]), gremlingo.T__.Constant(p["xx2"]), gremlingo.T__.Constant(p["xx3"]))}},
"g_unionXV_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.V().Values("name"))}},
"g_unionXVXv1X_VX4XX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.V(p["v1"]), gremlingo.T__.V(p["v4"])).Values("name")}},
"g_unionXV_hasLabelXsoftwareX_V_hasLabelXpersonXX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.V().HasLabel("software"), gremlingo.T__.V().HasLabel("person")).Values("name")}},
+ "g_unionXV_out_out_V_hasLabelXsoftwareXX_path": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.V().Out().Out(), gremlingo.T__.V().HasLabel("software")).Path()}},
+ "g_unionXV_out_out_V_hasLabelXsoftwareXX_path_byXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.V().Out().Out(), gremlingo.T__.V().HasLabel("software")).Path().By("name")}},
+ "g_unionXunionXV_out_outX_V_hasLabelXsoftwareXX_path_byXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.Union(gremlingo.T__.V().Out().Out()), gremlingo.T__.V().HasLabel("software")).Path().By("name")}},
+ "g_unionXinjectX1X_injectX2X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.Inject(1), gremlingo.T__.Inject(2))}},
"g_V_unionXconstantX1X_constantX2X_constantX3XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["v2"]).Union(gremlingo.T__.Constant(p["xx1"]), gremlingo.T__.Constant(p["xx2"]), gremlingo.T__.Constant(p["xx3"]))}},
"g_V_unionXout__inX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Union(gremlingo.T__.Out(), gremlingo.T__.In()).Values("name")}},
"g_VX1X_unionXrepeatXoutX_timesX2X__outX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Union(gremlingo.T__.Repeat(gremlingo.T__.Out()).Times(2), gremlingo.T__.Out()).Values("name")}},
@@ -101,6 +104,7 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_VX1_2X_unionXoutE_count__inE_count__outE_weight_sumX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"], p["vid2"]).Union(gremlingo.T__.OutE().Count(), gremlingo.T__.InE().Count(), gremlingo.T__.OutE().Values("weight").Sum())}},
"g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"], p["vid2"]).Local(gremlingo.T__.Union(gremlingo.T__.OutE().Count(), gremlingo.T__.InE().Count(), gremlingo.T__.OutE().Values("weight").Sum()))}},
"g_VX1_2X_localXunionXcountXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"], p["vid2"]).Local(gremlingo.T__.Union(gremlingo.T__.Count()))}},
+ "g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Union(gremlingo.T__.AddV("person").Property("name", "alice"), gremlingo.T__.AddV("person").Property("name", "bob"), gremlingo.T__.AddV("person").Property("name", "chris")).Values("name")}},
"g_V_valuesXageX_allXgtX32XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").All(gremlingo.P.Gt(32))}},
"g_V_valuesXageX_whereXisXP_gtX33XXX_fold_allXgtX33XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.T__.Is(gremlingo.P.Gt(33))).Fold().All(gremlingo.P.Gt(33))}},
"g_V_valuesXageX_order_byXdescX_fold_allXgtX10XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().By(gremlingo.Order.Desc).Fold().All(gremlingo.P.Gt(10))}},
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 5b7715da9f..d1ecb4216b 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
@@ -108,10 +108,13 @@ const gremlins = {
g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang: [function({g}) { return g.V().repeat("a",__.out("knows").repeat("b",__.out("created").filter(__.loops("a").is(0))).emit()).emit().values("lang") }],
g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name: [function({g, vid6}) { return g.V(vid6).repeat("a",__.both("created").simplePath()).emit(__.repeat("b",__.both("knows")).until(__.loops("b").as("b").where(__.loops("a").as("b"))).has("name","vadas")).dedup().values("name") }],
g_unionXX: [function({g}) { return g.union() }],
- g_unionXconstantX1X_constantX2X_constantX3XX: [function({g, xx1, xx3, xx2}) { return g.union(__.constant(xx1),__.constant(xx2),__.constant(xx3)) }],
g_unionXV_name: [function({g}) { return g.union(__.V().values("name")) }],
g_unionXVXv1X_VX4XX_name: [function({g, v4, v1}) { return g.union(__.V(v1),__.V(v4)).values("name") }],
g_unionXV_hasLabelXsoftwareX_V_hasLabelXpersonXX_name: [function({g}) { return g.union(__.V().hasLabel("software"),__.V().hasLabel("person")).values("name") }],
+ g_unionXV_out_out_V_hasLabelXsoftwareXX_path: [function({g}) { return g.union(__.V().out().out(),__.V().hasLabel("software")).path() }],
+ g_unionXV_out_out_V_hasLabelXsoftwareXX_path_byXnameX: [function({g}) { return g.union(__.V().out().out(),__.V().hasLabel("software")).path().by("name") }],
+ g_unionXunionXV_out_outX_V_hasLabelXsoftwareXX_path_byXnameX: [function({g}) { return g.union(__.union(__.V().out().out()),__.V().hasLabel("software")).path().by("name") }],
+ g_unionXinjectX1X_injectX2X: [function({g}) { return g.union(__.inject(1),__.inject(2)) }],
g_V_unionXconstantX1X_constantX2X_constantX3XX: [function({g, xx1, xx3, xx2, v2}) { return g.V(v2).union(__.constant(xx1),__.constant(xx2),__.constant(xx3)) }],
g_V_unionXout__inX_name: [function({g}) { return g.V().union(__.out(),__.in_()).values("name") }],
g_VX1X_unionXrepeatXoutX_timesX2X__outX_name: [function({g, vid1}) { return g.V(vid1).union(__.repeat(__.out()).times(2),__.out()).values("name") }],
@@ -121,6 +124,7 @@ const gremlins = {
g_VX1_2X_unionXoutE_count__inE_count__outE_weight_sumX: [function({g, vid2, vid1}) { return g.V(vid1,vid2).union(__.outE().count(),__.inE().count(),__.outE().values("weight").sum()) }],
g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX: [function({g, vid2, vid1}) { return g.V(vid1,vid2).local(__.union(__.outE().count(),__.inE().count(),__.outE().values("weight").sum())) }],
g_VX1_2X_localXunionXcountXX: [function({g, vid2, vid1}) { return g.V(vid1,vid2).local(__.union(__.count())) }],
+ g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name: [function({g}) { return g.union(__.addV("person").property("name","alice"),__.addV("person").property("name","bob"),__.addV("person").property("name","chris")).values("name") }],
g_V_valuesXageX_allXgtX32XX: [function({g}) { return g.V().values("age").all(P.gt(32)) }],
g_V_valuesXageX_whereXisXP_gtX33XXX_fold_allXgtX33XX: [function({g}) { return g.V().values("age").where(__.is(P.gt(33))).fold().all(P.gt(33)) }],
g_V_valuesXageX_order_byXdescX_fold_allXgtX10XX: [function({g}) { return g.V().values("age").order().by(Order.desc).fold().all(P.gt(10)) }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 3865df63c5..6a1f704358 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -90,10 +90,13 @@ world.gremlins = {
'g_V_repeatXa_outXknows_repeatXb_outXcreatedX_filterXloops_isX0XX_emit_lang': [(lambda g:g.V().repeat('a',__.out('knows').repeat('b',__.out('created').filter_(__.loops('a').is_(0))).emit()).emit().lang)],
'g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name': [(lambda g, vid6=None:g.V(vid6).repeat('a',__.both('created').simplePath()).emit(__.repeat('b',__.both('knows')).until(__.loops('b').as_('b').where(__.loops('a').as_('b'))).has('name','vadas')).dedup().name)],
'g_unionXX': [(lambda g:g.union())],
- 'g_unionXconstantX1X_constantX2X_constantX3XX': [(lambda g, xx1=None,xx3=None,xx2=None:g.union(__.constant(xx1),__.constant(xx2),__.constant(xx3)))],
'g_unionXV_name': [(lambda g:g.union(__.V().name))],
'g_unionXVXv1X_VX4XX_name': [(lambda g, v4=None,v1=None:g.union(__.V(v1),__.V(v4)).name)],
'g_unionXV_hasLabelXsoftwareX_V_hasLabelXpersonXX_name': [(lambda g:g.union(__.V().hasLabel('software'),__.V().hasLabel('person')).name)],
+ 'g_unionXV_out_out_V_hasLabelXsoftwareXX_path': [(lambda g:g.union(__.V().out().out(),__.V().hasLabel('software')).path())],
+ 'g_unionXV_out_out_V_hasLabelXsoftwareXX_path_byXnameX': [(lambda g:g.union(__.V().out().out(),__.V().hasLabel('software')).path().by('name'))],
+ 'g_unionXunionXV_out_outX_V_hasLabelXsoftwareXX_path_byXnameX': [(lambda g:g.union(__.union(__.V().out().out()),__.V().hasLabel('software')).path().by('name'))],
+ 'g_unionXinjectX1X_injectX2X': [(lambda g:g.union(__.inject(1),__.inject(2)))],
'g_V_unionXconstantX1X_constantX2X_constantX3XX': [(lambda g, xx1=None,xx3=None,xx2=None,v2=None:g.V(v2).union(__.constant(xx1),__.constant(xx2),__.constant(xx3)))],
'g_V_unionXout__inX_name': [(lambda g:g.V().union(__.out(),__.in_()).name)],
'g_VX1X_unionXrepeatXoutX_timesX2X__outX_name': [(lambda g, vid1=None:g.V(vid1).union(__.repeat(__.out()).times(2),__.out()).name)],
@@ -103,6 +106,7 @@ world.gremlins = {
'g_VX1_2X_unionXoutE_count__inE_count__outE_weight_sumX': [(lambda g, vid2=None,vid1=None:g.V(vid1,vid2).union(__.outE().count(),__.inE().count(),__.outE().weight.sum_()))],
'g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX': [(lambda g, vid2=None,vid1=None:g.V(vid1,vid2).local(__.union(__.outE().count(),__.inE().count(),__.outE().weight.sum_())))],
'g_VX1_2X_localXunionXcountXX': [(lambda g, vid2=None,vid1=None:g.V(vid1,vid2).local(__.union(__.count())))],
+ 'g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name': [(lambda g:g.union(__.addV('person').property('name','alice'),__.addV('person').property('name','bob'),__.addV('person').property('name','chris')).name)],
'g_V_valuesXageX_allXgtX32XX': [(lambda g:g.V().age.all_(P.gt(32)))],
'g_V_valuesXageX_whereXisXP_gtX33XXX_fold_allXgtX33XX': [(lambda g:g.V().age.where(__.is_(P.gt(33))).fold().all_(P.gt(33)))],
'g_V_valuesXageX_order_byXdescX_fold_allXgtX10XX': [(lambda g:g.V().age.order().by(Order.desc).fold().all_(P.gt(10)))],
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature
index c5a99a13c2..c30662afc9 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature
@@ -27,24 +27,6 @@ Feature: Step - union()
When iterated to list
Then the result should be empty
- # this use of union() is a bit like inject() so just gonna use that tag to ignore
- @GraphComputerVerificationInjectionNotSupported
- Scenario: g_unionXconstantX1X_constantX2X_constantX3XX
- Given the modern graph
- And using the parameter xx1 defined as "d[1].i"
- And using the parameter xx2 defined as "d[2].i"
- And using the parameter xx3 defined as "d[3].i"
- And the traversal of
- """
- g.union(constant(xx1), constant(xx2), constant(xx3))
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | d[1].i |
- | d[2].i |
- | d[3].i |
-
@GraphComputerVerificationMidVNotSupported
Scenario: g_unionXV_name
Given the modern graph
@@ -94,6 +76,64 @@ Feature: Step - union()
| ripple |
| peter |
+ @GraphComputerVerificationMidVNotSupported
+ Scenario: g_unionXV_out_out_V_hasLabelXsoftwareXX_path
+ Given the modern graph
+ And the traversal of
+ """
+ g.union(__.V().out().out(), __.V().hasLabel("software")).path()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | p[v[marko],v[josh],v[ripple]] |
+ | p[v[marko],v[josh],v[lop]] |
+ | p[v[lop]] |
+ | p[v[ripple]] |
+
+ @GraphComputerVerificationMidVNotSupported
+ Scenario: g_unionXV_out_out_V_hasLabelXsoftwareXX_path_byXnameX
+ Given the modern graph
+ And the traversal of
+ """
+ g.union(__.V().out().out(), __.V().hasLabel("software")).path().by("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | p[marko,josh,ripple] |
+ | p[marko,josh,lop] |
+ | p[lop] |
+ | p[ripple] |
+
+ @GraphComputerVerificationMidVNotSupported
+ Scenario: g_unionXunionXV_out_outX_V_hasLabelXsoftwareXX_path_byXnameX
+ Given the modern graph
+ And the traversal of
+ """
+ g.union(__.union(__.V().out().out()), __.V().hasLabel("software")).path().by("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | p[marko,josh,ripple] |
+ | p[marko,josh,lop] |
+ | p[lop] |
+ | p[ripple] |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_unionXinjectX1X_injectX2X
+ Given the modern graph
+ And the traversal of
+ """
+ g.union(__.inject(1), __.inject(2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[2].i |
+
Scenario: g_V_unionXconstantX1X_constantX2X_constantX3XX
Given the modern graph
And using the parameter xx1 defined as "d[1].i"
@@ -245,3 +285,18 @@ Feature: Step - union()
| result |
| d[1].l |
| d[1].l |
+
+ Scenario: g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name
+ Given the empty graph
+ And the traversal of
+ """
+ g.union(__.addV("person").property("name", "alice"),
+ __.addV("person").property("name", "bob"),
+ __.addV("person").property("name", "chris")).values("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | alice |
+ | bob |
+ | chris |
\ No newline at end of file