Merge branch '3.6-dev' into 3.7-dev
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index bd07daf..3603d64 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -287,13 +287,13 @@
* Fixed bug in bytecode translation of `g.tx().commit()` and `g.tx().rollback()` in all languages.
* Improved error message from `JavaTranslator` by including exception source.
* Added missing `short` serialization (`gx:Int16`) to GraphSONV2 and GraphSONV3 in `gremlin-python`.
-* Added tests for error handling for GLV's if tx.commit() is called remotely for graphs without transactions support.
+* Added tests for error handling for GLV's if `tx.commit()`` is called remotely for graphs without transactions support.
* Introduced multi-architecture AMD64/ARM64 docker images for gremlin-console.
* Fixed bug in `JavaTranslator` where `has(String, null)` could call `has(String, Traversal)` to generate an error.
* Fixed issue where server errors weren't being properly parsed when sending bytecode over HTTP.
-* Improved bulkset contains check for elements if all elements in bulkset are of the same type.
+* Improved `Bulkset` contains check for elements if all elements in `Bulkset` are of the same type.
* Fixed bug in `EarlyLimitStrategy` which was too aggressive when promoting `limit()` before `map()`.
-* Fixed bug in mid-traversal `mergeE()` where mutations in `sideEffect()` were being applied to the current traverser rather than a `onMatch` edge.
+* Prevented mid-traversal `mergeE()` and `mergeV()` from operating on an incoming `Traverser` that contains an `Element`.
* Improved performance of the application of `FilterRankingStrategy` for large traversals with deeply nested traversals by improving the cache operation.
[[release-3-6-6]]
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 4065d58..8c6b420 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -2871,6 +2871,13 @@
<1> Create three dogs.
<2> Stream the edge maps into `mergeE()` steps.
+WARNING: There is a bit of an inconsistency present when `mergeE()` is used as a start step versus when it is used
+mid-traversal. As a start step, `mergeE()` will promote the currently created or matched `Edge` to the child traversal,
+allowing you to directly update it like `option(onMatch, property('k', 'v').constant([:]))`. However, when `mergeE()` is
+used mid-traversal, the `Edge` is not promoted to the child traversal and the incoming traverser is used instead. Such
+behavior is essentially blocked to prevent accidental misuse and will result in an exception at execution time that will
+have a message like, "The incoming traverser for MergeEdgeStep cannot be an Element".
+
The `mergeE` step can be combined with the `mergeV` step (or any other step producing a `Vertex`) using the
`Merge.outV` and `Merge.inV` option modulators. These options can be used to "late-bind" the `OUT` and `IN`
vertices in the main merge argument and in the `onCreate` argument:
@@ -3101,6 +3108,13 @@
<4> Pixel exists now, so we will take this option.
<5> The `updated` property has now been added.
+WARNING: There is a bit of an inconsistency present when `mergeV()` is used as a start step versus when it is used
+mid-traversal. As a start step, `mergeV()` will promote the currently created or matched `Vertex` to the child
+traversal, allowing you to directly update it like `option(onMatch, property('k', 'v').constant([:]))`. However, when
+`mergeV()` is used mid-traversal, the `Vertex` is not promoted to the child traversal and the incoming traverser is used
+instead. Such behavior is essentially blocked to prevent accidental misuse and will result in an exception at execution
+time that will have a message like, "The incoming traverser for MergeVertexStep cannot be an Element".
+
*Additional References*
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#mergeV()++[`mergeV()`],
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
index 761426e..1010ca5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
@@ -34,6 +34,7 @@
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.LambdaFilterStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.Event;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
@@ -274,8 +275,11 @@
edges = IteratorUtils.peek(edges, e -> {
// override current traverser with the matched Edge so that the option() traversal can operate
- // on it properly
- traverser.set((S) e);
+ // on it properly. this should only work this way for the start step form to retain the original
+ // behavior for 3.6.0 where you might do g.inject(Map).mergeE() and want that Map to pass through.
+ // in 4.x this will be rectified such that the edge will always be promoted and you will be forced
+ // to select() the map if you did want the behavior.
+ if (isStart) traverser.set((S) e);
// assume good input from GraphTraversal - folks might drop in a T here even though it is immutable
final Map<String, ?> onMatchMap = materializeMap(traverser, onMatchTraversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
index c9a1cf1..d1166c9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
@@ -46,6 +46,7 @@
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -142,6 +143,14 @@
if (token == Merge.onCreate) {
this.onCreateTraversal = this.integrateChild(traversalOption);
} else if (token == Merge.onMatch) {
+ // add a guard rail to ensure that the incoming object is not an Element. this will prevent
+ // a possibly inadvertent mutation of the graph if you did something like g.V().mergeE(). for
+ // 3.x we won't allow this behavior at all but in 4.x we will make it consistent like it will
+ // be in 4.x
+ if (!isStart && traversalOption != null && !(traversalOption instanceof ConstantTraversal)) {
+ traversalOption.addStep(0, new GuardRailStep<>(traversalOption, getClass().getSimpleName()));
+ }
+
this.onMatchTraversal = this.integrateChild(traversalOption);
} else {
throw new UnsupportedOperationException(String.format("Option %s for Merge is not supported", token.name()));
@@ -374,4 +383,30 @@
protected abstract Set getAllowedTokens();
+ /**
+ * Guard rail to ensure that the incoming object is not an {@link Element}.
+ */
+ public static class GuardRailStep<S, E> extends ScalarMapStep<S, E> {
+ private final String stepType;
+
+ public GuardRailStep(final Traversal.Admin traversal, final String stepType) {
+ super(traversal);
+ this.stepType = stepType;
+ }
+
+ @Override
+ protected E map(final Traverser.Admin<S> t) {
+ if (t.get() instanceof Element) {
+ throw new IllegalArgumentException(
+ String.format("The incoming traverser for %s cannot be an Element", stepType));
+ }
+ return (E) t.get();
+ }
+
+ @Override
+ public String toString() {
+ return StringFactory.stepString(this);
+ }
+ }
+
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
index 713b839..6adc458 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
@@ -94,8 +94,11 @@
// attach the onMatch properties
vertices = IteratorUtils.peek(vertices, v -> {
- // if this was a start step the traverser is initialized with Boolean/false, so override that with
- // the matched Vertex so that the option() traversal can operate on it properly
+ // override current traverser with the matched Edge so that the option() traversal can operate
+ // on it properly. this should only work this way for the start step form to retain the original
+ // behavior for 3.6.0 where you might do g.inject(Map).mergeV() and want that Map to pass through.
+ // in 4.x this will be rectified such that the edge will always be promoted and you will be forced
+ // to select() the map if you did want the behavior.
if (isStart) traverser.set((S) v);
// assume good input from GraphTraversal - folks might drop in a T here even though it is immutable
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 873667a1..e520b2b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -912,8 +912,10 @@
{"g_mergeV_mergeE_combination_new_vertices", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]).As("outV").MergeV((IDictionary<object,object>) p["xx2"]).As("inV").MergeE((IDictionary<object,object>) p["xx3"]).Option(Merge.OutV, (ITraversal) __.Select<object>("outV")).Option(Merge.InV, (ITraversal) __.Select<object>("inV")), (g,p) =>g.V(), (g,p) =>g.E(), (g,p) =>g.V().Has("name","marko").Out("knows").Has("name","vadas")}},
{"g_mergeV_mergeE_combination_existing_vertices", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").AddV("person").Property("name","vadas"), (g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]).As("outV").MergeV((IDictionary<object,object>) p["xx2"]).As("inV").MergeE((IDictionary<object,object>) p["xx3"]).Option(Merge.OutV, (ITraversal) __.Select<object>("outV")).Option(Merge.InV, (ITraversal) __.Select<object>("inV")), (g,p) =>g.V(), (g,p) =>g.E(), (g,p) =>g.V().Has("name","marko").Out("knows").Has("name","vadas")}},
{"g_V_asXvX_mergeEXxx1X_optionXMerge_onMatch_xx2X_optionXMerge_outV_selectXvXX_optionXMerge_inV_selectXvXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.V().As("v").MergeE((IDictionary<object,object>) p["xx1"]).Option(Merge.OnMatch, (IDictionary<object,object>) p["xx2"]).Option(Merge.OutV, (ITraversal) __.Select<object>("v")).Option(Merge.InV, (ITraversal) __.Select<object>("v"))}},
- {"g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").As("a").AddV("person").Property("name","vadas").As("b").AddE("knows").Property("weight",1).From("a").To("b"), (g,p) =>g.V().MergeE((IDictionary<object,object>) p["xx1"]).Option(Merge.OnMatch, (ITraversal) __.SideEffect(__.Property("weight",0)).Constant<object>(new Dictionary<object,object> {})), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("weight",1), (g,p) =>g.E().HasLabel("knows").Has("weight",0), (g,p) =>g.V().Has("weight")}},
+ {"g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").As("a").AddV("person").Property("name","vadas").As("b").AddE("knows").Property("weight",1).From("a").To("b"), (g,p) =>g.V().MergeE((IDictionary<object,object>) p["xx1"]).Option(Merge.OnMatch, (ITraversal) __.SideEffect(__.Property("weight",0)).Constant<object>(new Dictionary<object,object> {}))}},
{"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").As("a").AddV("person").Property("name","vadas").As("b").AddE("knows").Property("weight",1).From("a").To("b"), (g,p) =>g.MergeE((IDictionary<object,object>) p["xx1"]).Option(Merge.OnMatch, (ITraversal) __.SideEffect(__.Property("weight",0)).Constant<object>(new Dictionary<object,object> {})), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("weight",1), (g,p) =>g.E().HasLabel("knows").Has("weight",0), (g,p) =>g.V().Has("weight")}},
+ {"g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_match", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko").AddV("person").Property("name","vadas").Property("age",27).As("vadas").AddV("software").Property("name","lop").Property("lang","java").As("lop").AddV("person").Property("name","josh").Property("age",32).As("josh").AddV("software").Property("name","ripple").Property("lang","java").As("ripple").AddV("person").Property("name","peter").Property("age",35).As("peter").AddE("knows").From("marko").To("vadas").Property("weight",0.5).AddE("knows").From("marko").To("josh").Property("weight",1.0).AddE("created").From("marko").To("lop").Property("weight",0.4).AddE("created").From("josh").To("ripple").Property("weight",1.0).AddE("created").From("josh").To("lop").Property("weight",0.4).AddE("created").From("peter").To("lop").Property("weight",0.2), (g,p) =>g.Inject(p["xx1"],p["xx1"],p["xx2"]).Fold().MergeE((ITraversal) __.Limit<object>(Scope.Local,1)).Option(Merge.OnCreate, (ITraversal) __.Range<object>(Scope.Local,1,2)).Option(Merge.OnMatch, (ITraversal) __.Tail<object>(Scope.Local)), (g,p) =>g.V(), (g,p) =>g.E(), (g,p) =>g.E().Has("created","N"), (g,p) =>g.V().Has("person","name","marko").OutE("knows").Has("created","N").InV().Has("person","name","vadas")}},
+ {"g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_create", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko").AddV("person").Property("name","vadas").Property("age",27).As("vadas").AddV("software").Property("name","lop").Property("lang","java").As("lop").AddV("person").Property("name","josh").Property("age",32).As("josh").AddV("software").Property("name","ripple").Property("lang","java").As("ripple").AddV("person").Property("name","peter").Property("age",35).As("peter").AddE("knows").From("marko").To("vadas").Property("weight",0.5).AddE("knows").From("marko").To("josh").Property("weight",1.0).AddE("created").From("marko").To("lop").Property("weight",0.4).AddE("created").From("josh").To("ripple").Property("weight",1.0).AddE("created").From("josh").To("lop").Property("weight",0.4).AddE("created").From("peter").To("lop").Property("weight",0.2), (g,p) =>g.Inject(p["xx1"],p["xx1"],p["xx2"]).Fold().MergeE((ITraversal) __.Limit<object>(Scope.Local,1)).Option(Merge.OnCreate, (ITraversal) __.Range<object>(Scope.Local,1,2)).Option(Merge.OnMatch, (ITraversal) __.Tail<object>(Scope.Local)), (g,p) =>g.V(), (g,p) =>g.E(), (g,p) =>g.E().HasNot("created"), (g,p) =>g.V().Has("person","name","marko").OutE("knows").HasNot("created").InV().Has("person","name","vadas"), (g,p) =>g.V().Has("person","name","vadas").OutE("self").HasNot("weight").InV().Has("person","name","vadas")}},
{"g_mergeVXemptyX_optionXonMatch_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.MergeV((IDictionary<object,object>) new Dictionary<object,object> {}).Option(Merge.OnMatch, (IDictionary<object,object>) null), (g,p) =>g.V().Has("person","name","marko").Has("age",29)}},
{"g_V_mergeVXemptyX_optionXonMatch_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.V().MergeV((IDictionary<object,object>) new Dictionary<object,object> {}).Option(Merge.OnMatch, (IDictionary<object,object>) null), (g,p) =>g.V().Has("person","name","marko").Has("age",29)}},
{"g_mergeVXnullX_optionXonCreate_label_null_name_markoX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"])}},
@@ -948,7 +950,7 @@
{"g_mergeXlabel_person_name_vadasX_optionXonMatch_age_35X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","vadas").Property("age",29).AddV("person").Property("name","vadas").Property("age",27), (g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]).Option(Merge.OnMatch, (IDictionary<object,object>) p["xx2"]), (g,p) =>g.V().Has("age",35), (g,p) =>g.V()}},
{"g_V_mapXmergeXlabel_person_name_joshXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","vadas").Property("age",29).AddV("person").Property("name","stephen").Property("age",27), (g,p) =>g.V().Map<object>(__.MergeV((IDictionary<object,object>) p["xx1"])), (g,p) =>g.V().Has("person","name","josh"), (g,p) =>g.V()}},
{"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property(Cardinality.List,"age",29).Property(Cardinality.List,"age",31).Property(Cardinality.List,"age",32), (g,p) =>g.WithSideEffect("c",p["xx1"]).WithSideEffect("m",p["xx2"]).MergeV((ITraversal) __.Select<object>("c")).Option(Merge.OnMatch, (ITraversal) __.SideEffect(__.Properties<object>("age").Drop()).Select<object>("m")), (g,p) =>g.V().Has("person","name","marko").Has("age",19), (g,p) =>g.V().Has("person","name","marko").Has("age")}},
- {"g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property(Cardinality.List,"age",29).Property(Cardinality.List,"age",31).Property(Cardinality.List,"age",32), (g,p) =>g.WithSideEffect("m",p["xx1"]).V().Has("person","name","marko").MergeV((IDictionary<object,object>) new Dictionary<object,object> {}).Option(Merge.OnMatch, (ITraversal) __.SideEffect(__.Properties<object>("age").Drop()).Select<object>("m")), (g,p) =>g.V().Has("person","name","marko").Has("age",19), (g,p) =>g.V().Has("person","name","marko").Has("age")}},
+ {"g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property(Cardinality.List,"age",29).Property(Cardinality.List,"age",31).Property(Cardinality.List,"age",32), (g,p) =>g.WithSideEffect("m",p["xx1"]).V().Has("person","name","marko").MergeV((IDictionary<object,object>) new Dictionary<object,object> {}).Option(Merge.OnMatch, (ITraversal) __.SideEffect(__.Properties<object>("age").Drop()).Select<object>("m"))}},
{"g_mergeV_onCreate_inheritance_existing", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","mike").Property(T.Id,"1"), (g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]).Option(Merge.OnCreate, (IDictionary<object,object>) p["xx2"]), (g,p) =>g.V(), (g,p) =>g.V("1").Has("person","name","mike")}},
{"g_mergeV_onCreate_inheritance_new_1", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]).Option(Merge.OnCreate, (IDictionary<object,object>) p["xx2"]), (g,p) =>g.V(), (g,p) =>g.V("1").Has("person","name","mike")}},
{"g_mergeV_onCreate_inheritance_new_2", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]).Option(Merge.OnCreate, (IDictionary<object,object>) p["xx2"]), (g,p) =>g.V(), (g,p) =>g.V("1").Has("person","name","mike")}},
@@ -973,6 +975,8 @@
{"g_mergeVXname_aliceX_optionXonCreate_age_setX81XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeV((IDictionary<object,object>) new Dictionary<object,object> {{"name", "alice"}, {T.Label, "person"}}).Option(Merge.OnCreate, (IDictionary<object,object>) new Dictionary<object,object> {{"age", CardinalityValue.Set(81)}}), (g,p) =>g.V().Has("person","name","alice").Has("age",81), (g,p) =>g.V().Has("person","name","alice").Has("age"), (g,p) =>g.V().Has("person","name","alice").Properties<object>("age")}},
{"g_mergeVXname_aliceX_optionXonCreate_age_singleX81X_age_81_setX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeV((IDictionary<object,object>) new Dictionary<object,object> {{"name", "alice"}, {T.Label, "person"}}).Option(Merge.OnCreate,new Dictionary<object,object> {{"age", 81}},Cardinality.Set), (g,p) =>g.V().Has("person","name","alice").Has("age",81), (g,p) =>g.V().Has("person","name","alice").Has("age"), (g,p) =>g.V().Has("person","name","alice").Properties<object>("age")}},
{"g_mergeV_hidden_label_key_onMatch_matched_prohibited", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeV((IDictionary<object,object>) new Dictionary<object,object> {}).Option(Merge.OnMatch, (IDictionary<object,object>) p["xx1"])}},
+ {"g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_match", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.Inject(p["xx1"],p["xx1"],p["xx2"]).Fold().MergeV((ITraversal) __.Limit<object>(Scope.Local,1)).Option(Merge.OnCreate, (ITraversal) __.Range<object>(Scope.Local,1,2)).Option(Merge.OnMatch, (ITraversal) __.Tail<object>(Scope.Local)), (g,p) =>g.V().Has("person","name","marko").Has("created","N"), (g,p) =>g.V()}},
+ {"g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_create", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.Inject(p["xx1"],p["xx1"],p["xx2"]).Fold().MergeV((ITraversal) __.Limit<object>(Scope.Local,1)).Option(Merge.OnCreate, (ITraversal) __.Range<object>(Scope.Local,1,2)).Option(Merge.OnMatch, (ITraversal) __.Tail<object>(Scope.Local)), (g,p) =>g.V().Has("person","name","stephen").HasNot("created"), (g,p) =>g.V()}},
{"g_V_age_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Min<object>()}},
{"g_V_foo_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Min<object>()}},
{"g_V_name_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Min<object>()}},
diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index d9a5a27..354891c 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -883,8 +883,10 @@
"g_mergeV_mergeE_combination_new_vertices": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(p["xx1"]).As("outV").MergeV(p["xx2"]).As("inV").MergeE(p["xx3"]).Option(gremlingo.Merge.OutV, gremlingo.T__.Select("outV")).Option(gremlingo.Merge.InV, gremlingo.T__.Select("inV"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", "marko").Out("knows").Has("name", "vadas")}},
"g_mergeV_mergeE_combination_existing_vertices": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").AddV("person").Property("name", "vadas")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(p["xx1"]).As("outV").MergeV(p["xx2"]).As("inV").MergeE(p["xx3"]).Option(gremlingo.Merge.OutV, gremlingo.T__.Select("outV")).Option(gremlingo.Merge.InV, gremlingo.T__.Select("inV"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", "marko").Out("knows").Has("name", "vadas")}},
"g_V_asXvX_mergeEXxx1X_optionXMerge_onMatch_xx2X_optionXMerge_outV_selectXvXX_optionXMerge_inV_selectXvXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().As("v").MergeE(p["xx1"]).Option(gremlingo.Merge.OnMatch, p["xx2"]).Option(gremlingo.Merge.OutV, gremlingo.T__.Select("v")).Option(gremlingo.Merge.InV, gremlingo.T__.Select("v"))}},
- "g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").As("a").AddV("person").Property("name", "vadas").As("b").AddE("knows").Property("weight", 1).From("a").To("b")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().MergeE(p["xx1"]).Option(gremlingo.Merge.OnMatch, gremlingo.T__.SideEffect(gremlingo.T__.Property("weight", 0)).Constant(map[interface{}]interface{}{}))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasLabel("knows").Has("weight", 1)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasLabel("knows").Has("weight", 0)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("weight")}},
+ "g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").As("a").AddV("person").Property("name", "vadas").As("b").AddE("knows").Property("weight", 1).From("a").To("b")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().MergeE(p["xx1"]).Option(gremlingo.Merge.OnMatch, gremlingo.T__.SideEffect(gremlingo.T__.Property("weight", 0)).Constant(map[interface{}]interface{}{}))}},
"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").As("a").AddV("person").Property("name", "vadas").As("b").AddE("knows").Property("weight", 1).From("a").To("b")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeE(p["xx1"]).Option(gremlingo.Merge.OnMatch, gremlingo.T__.SideEffect(gremlingo.T__.Property("weight", 0)).Constant(map[interface{}]interface{}{}))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasLabel("knows").Has("weight", 1)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasLabel("knows").Has("weight", 0)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("weight")}},
+ "g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_match": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("software").Property("name", "ripple").Property("lang", "java").As("ripple").AddV("person").Property("name", "peter").Property("age", 35).As("peter").AddE("knows").From("marko").To("vadas").Property("weight", 0.5).AddE("knows").From("marko").To("josh").Property("weight", 1.0).AddE("created").From("marko").To("lop").Property("weight", 0.4).AddE("created").From("josh").To("ripple").Property("weight", 1.0).AddE("created").From("josh").To("lop").Property("weight", 0.4).AddE("created").From("peter").To("lop").Property("weight", 0.2)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx1"], p["xx2"]).Fold().MergeE(gremlingo.T__.Limit(gremlingo.Scope.Local, 1)).Option(gremlingo.Merge.OnCreate, gremlingo.T__.Range(gremlingo.Scope.Local, 1, 2)).Option(gremlingo.Merge.OnMatch, gremlingo.T__.Tail(gremlingo.Scope.Local))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Has("created", "N")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").OutE("knows").Has("created", "N").InV().Has("person", "name", "vadas")}},
+ "g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_create": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("software").Property("name", "ripple").Property("lang", "java").As("ripple").AddV("person").Property("name", "peter").Property("age", 35).As("peter").AddE("knows").From("marko").To("vadas").Property("weight", 0.5).AddE("knows").From("marko").To("josh").Property("weight", 1.0).AddE("created").From("marko").To("lop").Property("weight", 0.4).AddE("created").From("josh").To("ripple").Property("weight", 1.0).AddE("created").From("josh").To("lop").Property("weight", 0.4).AddE("created").From("peter").To("lop").Property("weight", 0.2)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx1"], p["xx2"]).Fold().MergeE(gremlingo.T__.Limit(gremlingo.Scope.Local, 1)).Option(gremlingo.Merge.OnCreate, gremlingo.T__.Range(gremlingo.Scope.Local, 1, 2)).Option(gremlingo.Merge.OnMatch, gremlingo.T__.Tail(gremlingo.Scope.Local))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasNot("created")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").OutE("knows").HasNot("created").InV().Has("person", "name", "vadas")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "vadas").OutE("self").HasNot("weight").InV().Has("person", "name", "vadas")}},
"g_mergeVXemptyX_optionXonMatch_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(map[interface{}]interface{}{}).Option(gremlingo.Merge.OnMatch, nil)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Has("age", 29)}},
"g_V_mergeVXemptyX_optionXonMatch_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().MergeV(map[interface{}]interface{}{}).Option(gremlingo.Merge.OnMatch, nil)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Has("age", 29)}},
"g_mergeVXnullX_optionXonCreate_label_null_name_markoX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(p["xx1"])}},
@@ -919,7 +921,7 @@
"g_mergeXlabel_person_name_vadasX_optionXonMatch_age_35X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "vadas").Property("age", 29).AddV("person").Property("name", "vadas").Property("age", 27)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(p["xx1"]).Option(gremlingo.Merge.OnMatch, p["xx2"])}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", 35)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}},
"g_V_mapXmergeXlabel_person_name_joshXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "vadas").Property("age", 29).AddV("person").Property("name", "stephen").Property("age", 27)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Map(gremlingo.T__.MergeV(p["xx1"]))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "josh")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}},
"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property(gremlingo.Cardinality.List, "age", 29).Property(gremlingo.Cardinality.List, "age", 31).Property(gremlingo.Cardinality.List, "age", 32)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSideEffect("c", p["xx1"]).WithSideEffect("m", p["xx2"]).MergeV(gremlingo.T__.Select("c")).Option(gremlingo.Merge.OnMatch, gremlingo.T__.SideEffect(gremlingo.T__.Properties("age").Drop()).Select("m"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Has("age", 19)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Has("age")}},
- "g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property(gremlingo.Cardinality.List, "age", 29).Property(gremlingo.Cardinality.List, "age", 31).Property(gremlingo.Cardinality.List, "age", 32)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSideEffect("m", p["xx1"]).V().Has("person", "name", "marko").MergeV(map[interface{}]interface{}{}).Option(gremlingo.Merge.OnMatch, gremlingo.T__.SideEffect(gremlingo.T__.Properties("age").Drop()).Select("m"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Has("age", 19)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Has("age")}},
+ "g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property(gremlingo.Cardinality.List, "age", 29).Property(gremlingo.Cardinality.List, "age", 31).Property(gremlingo.Cardinality.List, "age", 32)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSideEffect("m", p["xx1"]).V().Has("person", "name", "marko").MergeV(map[interface{}]interface{}{}).Option(gremlingo.Merge.OnMatch, gremlingo.T__.SideEffect(gremlingo.T__.Properties("age").Drop()).Select("m"))}},
"g_mergeV_onCreate_inheritance_existing": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "mike").Property(gremlingo.T.Id, "1")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(p["xx1"]).Option(gremlingo.Merge.OnCreate, p["xx2"])}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V("1").Has("person", "name", "mike")}},
"g_mergeV_onCreate_inheritance_new_1": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(p["xx1"]).Option(gremlingo.Merge.OnCreate, p["xx2"])}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V("1").Has("person", "name", "mike")}},
"g_mergeV_onCreate_inheritance_new_2": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(p["xx1"]).Option(gremlingo.Merge.OnCreate, p["xx2"])}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V("1").Has("person", "name", "mike")}},
@@ -944,6 +946,8 @@
"g_mergeVXname_aliceX_optionXonCreate_age_setX81XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(map[interface{}]interface{}{"name": "alice", gremlingo.T.Label: "person"}).Option(gremlingo.Merge.OnCreate, map[interface{}]interface{}{"age": gremlingo.CardinalityValue.Set(81)})}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "alice").Has("age", 81)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "alice").Has("age")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "alice").Properties("age")}},
"g_mergeVXname_aliceX_optionXonCreate_age_singleX81X_age_81_setX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(map[interface{}]interface{}{"name": "alice", gremlingo.T.Label: "person"}).Option(gremlingo.Merge.OnCreate, map[interface{}]interface{}{"age": 81}, gremlingo.Cardinality.Set)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "alice").Has("age", 81)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "alice").Has("age")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "alice").Properties("age")}},
"g_mergeV_hidden_label_key_onMatch_matched_prohibited": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.MergeV(map[interface{}]interface{}{}).Option(gremlingo.Merge.OnMatch, p["xx1"])}},
+ "g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_match": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx1"], p["xx2"]).Fold().MergeV(gremlingo.T__.Limit(gremlingo.Scope.Local, 1)).Option(gremlingo.Merge.OnCreate, gremlingo.T__.Range(gremlingo.Scope.Local, 1, 2)).Option(gremlingo.Merge.OnMatch, gremlingo.T__.Tail(gremlingo.Scope.Local))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Has("created", "N")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}},
+ "g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_create": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx1"], p["xx2"]).Fold().MergeV(gremlingo.T__.Limit(gremlingo.Scope.Local, 1)).Option(gremlingo.Merge.OnCreate, gremlingo.T__.Range(gremlingo.Scope.Local, 1, 2)).Option(gremlingo.Merge.OnMatch, gremlingo.T__.Tail(gremlingo.Scope.Local))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "stephen").HasNot("created")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}},
"g_V_age_min": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Min()}},
"g_V_foo_min": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("foo").Min()}},
"g_V_name_min": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Min()}},
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 79f4335..8054279 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
@@ -903,8 +903,10 @@
g_mergeV_mergeE_combination_new_vertices: [function({g, xx1, xx3, xx2}) { return g.mergeV(xx1).as("outV").mergeV(xx2).as("inV").mergeE(xx3).option(Merge.outV,__.select("outV")).option(Merge.inV,__.select("inV")) }, function({g, xx1, xx3, xx2}) { return g.V() }, function({g, xx1, xx3, xx2}) { return g.E() }, function({g, xx1, xx3, xx2}) { return g.V().has("name","marko").out("knows").has("name","vadas") }],
g_mergeV_mergeE_combination_existing_vertices: [function({g, xx1, xx3, xx2}) { return g.addV("person").property("name","marko").addV("person").property("name","vadas") }, function({g, xx1, xx3, xx2}) { return g.mergeV(xx1).as("outV").mergeV(xx2).as("inV").mergeE(xx3).option(Merge.outV,__.select("outV")).option(Merge.inV,__.select("inV")) }, function({g, xx1, xx3, xx2}) { return g.V() }, function({g, xx1, xx3, xx2}) { return g.E() }, function({g, xx1, xx3, xx2}) { return g.V().has("name","marko").out("knows").has("name","vadas") }],
g_V_asXvX_mergeEXxx1X_optionXMerge_onMatch_xx2X_optionXMerge_outV_selectXvXX_optionXMerge_inV_selectXvXX: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29) }, function({g, xx1, xx2}) { return g.V().as("v").mergeE(xx1).option(Merge.onMatch,xx2).option(Merge.outV,__.select("v")).option(Merge.inV,__.select("v")) }],
- g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX: [function({g, xx1}) { return g.addV("person").property("name","marko").as("a").addV("person").property("name","vadas").as("b").addE("knows").property("weight",1).from_("a").to("b") }, function({g, xx1}) { return g.V().mergeE(xx1).option(Merge.onMatch,__.sideEffect(__.property("weight",0)).constant(new Map([]))) }, function({g, xx1}) { return g.V() }, function({g, xx1}) { return g.E().hasLabel("knows").has("weight",1) }, function({g, xx1}) { return g.E().hasLabel("knows").has("weight",0) }, function({g, xx1}) { return g.V().has("weight") }],
+ g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX: [function({g, xx1}) { return g.addV("person").property("name","marko").as("a").addV("person").property("name","vadas").as("b").addE("knows").property("weight",1).from_("a").to("b") }, function({g, xx1}) { return g.V().mergeE(xx1).option(Merge.onMatch,__.sideEffect(__.property("weight",0)).constant(new Map([]))) }],
g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX: [function({g, xx1}) { return g.addV("person").property("name","marko").as("a").addV("person").property("name","vadas").as("b").addE("knows").property("weight",1).from_("a").to("b") }, function({g, xx1}) { return g.mergeE(xx1).option(Merge.onMatch,__.sideEffect(__.property("weight",0)).constant(new Map([]))) }, function({g, xx1}) { return g.V() }, function({g, xx1}) { return g.E().hasLabel("knows").has("weight",1) }, function({g, xx1}) { return g.E().hasLabel("knows").has("weight",0) }, function({g, xx1}) { return g.V().has("weight") }],
+ g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_match: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko").addV("person").property("name","vadas").property("age",27).as("vadas").addV("software").property("name","lop").property("lang","java").as("lop").addV("person").property("name","josh").property("age",32).as("josh").addV("software").property("name","ripple").property("lang","java").as("ripple").addV("person").property("name","peter").property("age",35).as("peter").addE("knows").from_("marko").to("vadas").property("weight",0.5).addE("knows").from_("marko").to("josh").property("weight",1.0).addE("created").from_("marko").to("lop").property("weight",0.4).addE("created").from_("josh").to("ripple").property("weight",1.0).addE("created").from_("josh").to("lop").property("weight",0.4).addE("created").from_("peter").to("lop").property("weight",0.2) }, function({g, xx1, xx2}) { return g.inject(xx1,xx1,xx2).fold().mergeE(__.limit(Scope.local,1)).option(Merge.onCreate,__.range(Scope.local,1,2)).option(Merge.onMatch,__.tail(Scope.local)) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.E() }, function({g, xx1, xx2}) { return g.E().has("created","N") }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").outE("knows").has("created","N").inV().has("person","name","vadas") }],
+ g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_create: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko").addV("person").property("name","vadas").property("age",27).as("vadas").addV("software").property("name","lop").property("lang","java").as("lop").addV("person").property("name","josh").property("age",32).as("josh").addV("software").property("name","ripple").property("lang","java").as("ripple").addV("person").property("name","peter").property("age",35).as("peter").addE("knows").from_("marko").to("vadas").property("weight",0.5).addE("knows").from_("marko").to("josh").property("weight",1.0).addE("created").from_("marko").to("lop").property("weight",0.4).addE("created").from_("josh").to("ripple").property("weight",1.0).addE("created").from_("josh").to("lop").property("weight",0.4).addE("created").from_("peter").to("lop").property("weight",0.2) }, function({g, xx1, xx2}) { return g.inject(xx1,xx1,xx2).fold().mergeE(__.limit(Scope.local,1)).option(Merge.onCreate,__.range(Scope.local,1,2)).option(Merge.onMatch,__.tail(Scope.local)) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.E() }, function({g, xx1, xx2}) { return g.E().hasNot("created") }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").outE("knows").hasNot("created").inV().has("person","name","vadas") }, function({g, xx1, xx2}) { return g.V().has("person","name","vadas").outE("self").hasNot("weight").inV().has("person","name","vadas") }],
g_mergeVXemptyX_optionXonMatch_nullX: [function({g}) { return g.addV("person").property("name","marko").property("age",29) }, function({g}) { return g.mergeV(new Map([])).option(Merge.onMatch,null) }, function({g}) { return g.V().has("person","name","marko").has("age",29) }],
g_V_mergeVXemptyX_optionXonMatch_nullX: [function({g}) { return g.addV("person").property("name","marko").property("age",29) }, function({g}) { return g.V().mergeV(new Map([])).option(Merge.onMatch,null) }, function({g}) { return g.V().has("person","name","marko").has("age",29) }],
g_mergeVXnullX_optionXonCreate_label_null_name_markoX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29) }, function({g, xx1}) { return g.mergeV(xx1) }],
@@ -939,7 +941,7 @@
g_mergeXlabel_person_name_vadasX_optionXonMatch_age_35X: [function({g, xx1, xx2}) { return g.addV("person").property("name","vadas").property("age",29).addV("person").property("name","vadas").property("age",27) }, function({g, xx1, xx2}) { return g.mergeV(xx1).option(Merge.onMatch,xx2) }, function({g, xx1, xx2}) { return g.V().has("age",35) }, function({g, xx1, xx2}) { return g.V() }],
g_V_mapXmergeXlabel_person_name_joshXX: [function({g, xx1}) { return g.addV("person").property("name","vadas").property("age",29).addV("person").property("name","stephen").property("age",27) }, function({g, xx1}) { return g.V().map(__.mergeV(xx1)) }, function({g, xx1}) { return g.V().has("person","name","josh") }, function({g, xx1}) { return g.V() }],
g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property(Cardinality.list,"age",29).property(Cardinality.list,"age",31).property(Cardinality.list,"age",32) }, function({g, xx1, xx2}) { return g.withSideEffect("c",xx1).withSideEffect("m",xx2).mergeV(__.select("c")).option(Merge.onMatch,__.sideEffect(__.properties("age").drop()).select("m")) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("age",19) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("age") }],
- g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option: [function({g, xx1}) { return g.addV("person").property("name","marko").property(Cardinality.list,"age",29).property(Cardinality.list,"age",31).property(Cardinality.list,"age",32) }, function({g, xx1}) { return g.withSideEffect("m",xx1).V().has("person","name","marko").mergeV(new Map([])).option(Merge.onMatch,__.sideEffect(__.properties("age").drop()).select("m")) }, function({g, xx1}) { return g.V().has("person","name","marko").has("age",19) }, function({g, xx1}) { return g.V().has("person","name","marko").has("age") }],
+ g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option: [function({g, xx1}) { return g.addV("person").property("name","marko").property(Cardinality.list,"age",29).property(Cardinality.list,"age",31).property(Cardinality.list,"age",32) }, function({g, xx1}) { return g.withSideEffect("m",xx1).V().has("person","name","marko").mergeV(new Map([])).option(Merge.onMatch,__.sideEffect(__.properties("age").drop()).select("m")) }],
g_mergeV_onCreate_inheritance_existing: [function({g, xx1, xx2}) { return g.addV("person").property("name","mike").property(T.id,"1") }, function({g, xx1, xx2}) { return g.mergeV(xx1).option(Merge.onCreate,xx2) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.V("1").has("person","name","mike") }],
g_mergeV_onCreate_inheritance_new_1: [function({g, xx1, xx2}) { return g.mergeV(xx1).option(Merge.onCreate,xx2) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.V("1").has("person","name","mike") }],
g_mergeV_onCreate_inheritance_new_2: [function({g, xx1, xx2}) { return g.mergeV(xx1).option(Merge.onCreate,xx2) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.V("1").has("person","name","mike") }],
@@ -964,6 +966,8 @@
g_mergeVXname_aliceX_optionXonCreate_age_setX81XX: [function({g}) { return g.mergeV(new Map([["name","alice"],[T.label,"person"]])).option(Merge.onCreate,new Map([["age",CardinalityValue.set(81)]])) }, function({g}) { return g.V().has("person","name","alice").has("age",81) }, function({g}) { return g.V().has("person","name","alice").has("age") }, function({g}) { return g.V().has("person","name","alice").properties("age") }],
g_mergeVXname_aliceX_optionXonCreate_age_singleX81X_age_81_setX: [function({g}) { return g.mergeV(new Map([["name","alice"],[T.label,"person"]])).option(Merge.onCreate,new Map([["age",81]]),Cardinality.set) }, function({g}) { return g.V().has("person","name","alice").has("age",81) }, function({g}) { return g.V().has("person","name","alice").has("age") }, function({g}) { return g.V().has("person","name","alice").properties("age") }],
g_mergeV_hidden_label_key_onMatch_matched_prohibited: [function({g, xx1}) { return g.mergeV(new Map([])).option(Merge.onMatch,xx1) }],
+ g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_match: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29) }, function({g, xx1, xx2}) { return g.inject(xx1,xx1,xx2).fold().mergeV(__.limit(Scope.local,1)).option(Merge.onCreate,__.range(Scope.local,1,2)).option(Merge.onMatch,__.tail(Scope.local)) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("created","N") }, function({g, xx1, xx2}) { return g.V() }],
+ g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_create: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29) }, function({g, xx1, xx2}) { return g.inject(xx1,xx1,xx2).fold().mergeV(__.limit(Scope.local,1)).option(Merge.onCreate,__.range(Scope.local,1,2)).option(Merge.onMatch,__.tail(Scope.local)) }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen").hasNot("created") }, function({g, xx1, xx2}) { return g.V() }],
g_V_age_min: [function({g}) { return g.V().values("age").min() }],
g_V_foo_min: [function({g}) { return g.V().values("foo").min() }],
g_V_name_min: [function({g}) { return g.V().values("name").min() }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 68fb4db..a17343d 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -885,8 +885,10 @@
'g_mergeV_mergeE_combination_new_vertices': [(lambda g, xx1=None,xx3=None,xx2=None:g.merge_v(xx1).as_('outV').merge_v(xx2).as_('inV').merge_e(xx3).option(Merge.out_v,__.select('outV')).option(Merge.in_v,__.select('inV'))), (lambda g, xx1=None,xx3=None,xx2=None:g.V()), (lambda g, xx1=None,xx3=None,xx2=None:g.E()), (lambda g, xx1=None,xx3=None,xx2=None:g.V().has('name','marko').out('knows').has('name','vadas'))],
'g_mergeV_mergeE_combination_existing_vertices': [(lambda g, xx1=None,xx3=None,xx2=None:g.addV('person').property('name','marko').addV('person').property('name','vadas')), (lambda g, xx1=None,xx3=None,xx2=None:g.merge_v(xx1).as_('outV').merge_v(xx2).as_('inV').merge_e(xx3).option(Merge.out_v,__.select('outV')).option(Merge.in_v,__.select('inV'))), (lambda g, xx1=None,xx3=None,xx2=None:g.V()), (lambda g, xx1=None,xx3=None,xx2=None:g.E()), (lambda g, xx1=None,xx3=None,xx2=None:g.V().has('name','marko').out('knows').has('name','vadas'))],
'g_V_asXvX_mergeEXxx1X_optionXMerge_onMatch_xx2X_optionXMerge_outV_selectXvXX_optionXMerge_inV_selectXvXX': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29)), (lambda g, xx1=None,xx2=None:g.V().as_('v').merge_e(xx1).option(Merge.on_match,xx2).option(Merge.out_v,__.select('v')).option(Merge.in_v,__.select('v')))],
- 'g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX': [(lambda g, xx1=None:g.addV('person').property('name','marko').as_('a').addV('person').property('name','vadas').as_('b').addE('knows').property('weight',1).from_('a').to('b')), (lambda g, xx1=None:g.V().merge_e(xx1).option(Merge.on_match,__.sideEffect(__.property('weight',0)).constant({}))), (lambda g, xx1=None:g.V()), (lambda g, xx1=None:g.E().hasLabel('knows').has('weight',1)), (lambda g, xx1=None:g.E().hasLabel('knows').has('weight',0)), (lambda g, xx1=None:g.V().has('weight'))],
+ 'g_V_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX': [(lambda g, xx1=None:g.addV('person').property('name','marko').as_('a').addV('person').property('name','vadas').as_('b').addE('knows').property('weight',1).from_('a').to('b')), (lambda g, xx1=None:g.V().merge_e(xx1).option(Merge.on_match,__.sideEffect(__.property('weight',0)).constant({})))],
'g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX': [(lambda g, xx1=None:g.addV('person').property('name','marko').as_('a').addV('person').property('name','vadas').as_('b').addE('knows').property('weight',1).from_('a').to('b')), (lambda g, xx1=None:g.merge_e(xx1).option(Merge.on_match,__.sideEffect(__.property('weight',0)).constant({}))), (lambda g, xx1=None:g.V()), (lambda g, xx1=None:g.E().hasLabel('knows').has('weight',1)), (lambda g, xx1=None:g.E().hasLabel('knows').has('weight',0)), (lambda g, xx1=None:g.V().has('weight'))],
+ 'g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_match': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko').addV('person').property('name','vadas').property('age',27).as_('vadas').addV('software').property('name','lop').property('lang','java').as_('lop').addV('person').property('name','josh').property('age',32).as_('josh').addV('software').property('name','ripple').property('lang','java').as_('ripple').addV('person').property('name','peter').property('age',35).as_('peter').addE('knows').from_('marko').to('vadas').property('weight',float(0.5)).addE('knows').from_('marko').to('josh').property('weight',float(1.0)).addE('created').from_('marko').to('lop').property('weight',float(0.4)).addE('created').from_('josh').to('ripple').property('weight',float(1.0)).addE('created').from_('josh').to('lop').property('weight',float(0.4)).addE('created').from_('peter').to('lop').property('weight',float(0.2))), (lambda g, xx1=None,xx2=None:g.inject(xx1,xx1,xx2).fold().merge_e(__.limit(Scope.local,1)).option(Merge.on_create,__.range_(Scope.local,1,2)).option(Merge.on_match,__.tail(Scope.local))), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.E()), (lambda g, xx1=None,xx2=None:g.E().has('created','N')), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').outE('knows').has('created','N').in_v().has('person','name','vadas'))],
+ 'g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_create': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko').addV('person').property('name','vadas').property('age',27).as_('vadas').addV('software').property('name','lop').property('lang','java').as_('lop').addV('person').property('name','josh').property('age',32).as_('josh').addV('software').property('name','ripple').property('lang','java').as_('ripple').addV('person').property('name','peter').property('age',35).as_('peter').addE('knows').from_('marko').to('vadas').property('weight',float(0.5)).addE('knows').from_('marko').to('josh').property('weight',float(1.0)).addE('created').from_('marko').to('lop').property('weight',float(0.4)).addE('created').from_('josh').to('ripple').property('weight',float(1.0)).addE('created').from_('josh').to('lop').property('weight',float(0.4)).addE('created').from_('peter').to('lop').property('weight',float(0.2))), (lambda g, xx1=None,xx2=None:g.inject(xx1,xx1,xx2).fold().merge_e(__.limit(Scope.local,1)).option(Merge.on_create,__.range_(Scope.local,1,2)).option(Merge.on_match,__.tail(Scope.local))), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.E()), (lambda g, xx1=None,xx2=None:g.E().hasNot('created')), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').outE('knows').hasNot('created').in_v().has('person','name','vadas')), (lambda g, xx1=None,xx2=None:g.V().has('person','name','vadas').outE('self').hasNot('weight').in_v().has('person','name','vadas'))],
'g_mergeVXemptyX_optionXonMatch_nullX': [(lambda g:g.addV('person').property('name','marko').property('age',29)), (lambda g:g.merge_v({}).option(Merge.on_match,None)), (lambda g:g.V().has('person','name','marko').has('age',29))],
'g_V_mergeVXemptyX_optionXonMatch_nullX': [(lambda g:g.addV('person').property('name','marko').property('age',29)), (lambda g:g.V().merge_v({}).option(Merge.on_match,None)), (lambda g:g.V().has('person','name','marko').has('age',29))],
'g_mergeVXnullX_optionXonCreate_label_null_name_markoX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29)), (lambda g, xx1=None:g.merge_v(xx1))],
@@ -921,7 +923,7 @@
'g_mergeXlabel_person_name_vadasX_optionXonMatch_age_35X': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','vadas').property('age',29).addV('person').property('name','vadas').property('age',27)), (lambda g, xx1=None,xx2=None:g.merge_v(xx1).option(Merge.on_match,xx2)), (lambda g, xx1=None,xx2=None:g.V().has('age',35)), (lambda g, xx1=None,xx2=None:g.V())],
'g_V_mapXmergeXlabel_person_name_joshXX': [(lambda g, xx1=None:g.addV('person').property('name','vadas').property('age',29).addV('person').property('name','stephen').property('age',27)), (lambda g, xx1=None:g.V().map(__.merge_v(xx1))), (lambda g, xx1=None:g.V().has('person','name','josh')), (lambda g, xx1=None:g.V())],
'g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property(Cardinality.list_,'age',29).property(Cardinality.list_,'age',31).property(Cardinality.list_,'age',32)), (lambda g, xx1=None,xx2=None:g.withSideEffect('c',xx1).withSideEffect('m',xx2).merge_v(__.select('c')).option(Merge.on_match,__.sideEffect(__.properties('age').drop()).select('m'))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('age',19)), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('age'))],
- 'g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option': [(lambda g, xx1=None:g.addV('person').property('name','marko').property(Cardinality.list_,'age',29).property(Cardinality.list_,'age',31).property(Cardinality.list_,'age',32)), (lambda g, xx1=None:g.withSideEffect('m',xx1).V().has('person','name','marko').merge_v({}).option(Merge.on_match,__.sideEffect(__.properties('age').drop()).select('m'))), (lambda g, xx1=None:g.V().has('person','name','marko').has('age',19)), (lambda g, xx1=None:g.V().has('person','name','marko').has('age'))],
+ 'g_withSideEffectXm_age_19X_V_hasXperson_name_markoX_mergeVXselectXcXX_optionXonMatch_sideEffectXpropertiesXageX_dropX_selectXmXX_option': [(lambda g, xx1=None:g.addV('person').property('name','marko').property(Cardinality.list_,'age',29).property(Cardinality.list_,'age',31).property(Cardinality.list_,'age',32)), (lambda g, xx1=None:g.withSideEffect('m',xx1).V().has('person','name','marko').merge_v({}).option(Merge.on_match,__.sideEffect(__.properties('age').drop()).select('m')))],
'g_mergeV_onCreate_inheritance_existing': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','mike').property(T.id_,'1')), (lambda g, xx1=None,xx2=None:g.merge_v(xx1).option(Merge.on_create,xx2)), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.V('1').has('person','name','mike'))],
'g_mergeV_onCreate_inheritance_new_1': [(lambda g, xx1=None,xx2=None:g.merge_v(xx1).option(Merge.on_create,xx2)), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.V('1').has('person','name','mike'))],
'g_mergeV_onCreate_inheritance_new_2': [(lambda g, xx1=None,xx2=None:g.merge_v(xx1).option(Merge.on_create,xx2)), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.V('1').has('person','name','mike'))],
@@ -946,6 +948,8 @@
'g_mergeVXname_aliceX_optionXonCreate_age_setX81XX': [(lambda g:g.merge_v({'name':'alice',T.label:'person'}).option(Merge.on_create,{'age':CardinalityValue.set_(81)})), (lambda g:g.V().has('person','name','alice').has('age',81)), (lambda g:g.V().has('person','name','alice').has('age')), (lambda g:g.V().has('person','name','alice').properties('age'))],
'g_mergeVXname_aliceX_optionXonCreate_age_singleX81X_age_81_setX': [(lambda g:g.merge_v({'name':'alice',T.label:'person'}).option(Merge.on_create,{'age':81},Cardinality.set_)), (lambda g:g.V().has('person','name','alice').has('age',81)), (lambda g:g.V().has('person','name','alice').has('age')), (lambda g:g.V().has('person','name','alice').properties('age'))],
'g_mergeV_hidden_label_key_onMatch_matched_prohibited': [(lambda g, xx1=None:g.merge_v({}).option(Merge.on_match,xx1))],
+ 'g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_match': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29)), (lambda g, xx1=None,xx2=None:g.inject(xx1,xx1,xx2).fold().merge_v(__.limit(Scope.local,1)).option(Merge.on_create,__.range_(Scope.local,1,2)).option(Merge.on_match,__.tail(Scope.local))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('created','N')), (lambda g, xx1=None,xx2=None:g.V())],
+ 'g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_create': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29)), (lambda g, xx1=None,xx2=None:g.inject(xx1,xx1,xx2).fold().merge_v(__.limit(Scope.local,1)).option(Merge.on_create,__.range_(Scope.local,1,2)).option(Merge.on_match,__.tail(Scope.local))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen').hasNot('created')), (lambda g, xx1=None,xx2=None:g.V())],
'g_V_age_min': [(lambda g:g.V().age.min_())],
'g_V_foo_min': [(lambda g:g.V().foo.min_())],
'g_V_name_min': [(lambda g:g.V().name.min_())],
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
index 4585a46..cea0550 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
@@ -857,11 +857,7 @@
option(Merge.onMatch, __.sideEffect(__.property("weight", 0)).constant([:]))
"""
When iterated to list
- Then the result should have a count of 2
- And the graph should return 2 for count of "g.V()"
- And the graph should return 0 for count of "g.E().hasLabel(\"knows\").has(\"weight\",1)"
- And the graph should return 1 for count of "g.E().hasLabel(\"knows\").has(\"weight\",0)"
- And the graph should return 0 for count of "g.V().has(\"weight\")"
+ Then the traversal will raise an error with message containing text of "The incoming traverser for MergeEdgeStep cannot be an Element"
Scenario: g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonMatch_sideEffectXpropertyXweight_0XX_constantXemptyXX
Given the empty graph
@@ -882,4 +878,73 @@
And the graph should return 2 for count of "g.V()"
And the graph should return 0 for count of "g.E().hasLabel(\"knows\").has(\"weight\",1)"
And the graph should return 1 for count of "g.E().hasLabel(\"knows\").has(\"weight\",0)"
- And the graph should return 0 for count of "g.V().has(\"weight\")"
\ No newline at end of file
+ And the graph should return 0 for count of "g.V().has(\"weight\")"
+
+ Scenario: g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_match
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).as("marko").
+ addV("person").property("name", "vadas").property("age", 27).as("vadas").
+ addV("software").property("name", "lop").property("lang", "java").as("lop").
+ addV("person").property("name","josh").property("age", 32).as("josh").
+ addV("software").property("name", "ripple").property("lang", "java").as("ripple").
+ addV("person").property("name", "peter").property("age", 35).as('peter').
+ addE("knows").from("marko").to("vadas").property("weight", 0.5d).
+ addE("knows").from("marko").to("josh").property("weight", 1.0d).
+ addE("created").from("marko").to("lop").property("weight", 0.4d).
+ addE("created").from("josh").to("ripple").property("weight", 1.0d).
+ addE("created").from("josh").to("lop").property("weight", 0.4d).
+ addE("created").from("peter").to("lop").property("weight", 0.2d)
+ """
+ And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[marko]\", \"D[IN]\":\"v[vadas]\"}]"
+ And using the parameter xx2 defined as "m[{\"created\": \"N\"}]"
+ And the traversal of
+ """
+ g.inject(xx1, xx1, xx2).
+ fold().
+ mergeE(__.limit(Scope.local,1)).
+ option(Merge.onCreate, __.range(Scope.local, 1, 2)).
+ option(Merge.onMatch, __.tail(Scope.local))
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 6 for count of "g.V()"
+ And the graph should return 6 for count of "g.E()"
+ And the graph should return 1 for count of "g.E().has(\"created\",\"N\")"
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\").outE(\"knows\").has(\"created\",\"N\").inV().has(\"person\",\"name\",\"vadas\")"
+
+ Scenario: g_injectXlist1_list2X_mergeEXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2XX_optionXonMatch_tailXlocalXX_to_create
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).as("marko").
+ addV("person").property("name", "vadas").property("age", 27).as("vadas").
+ addV("software").property("name", "lop").property("lang", "java").as("lop").
+ addV("person").property("name","josh").property("age", 32).as("josh").
+ addV("software").property("name", "ripple").property("lang", "java").as("ripple").
+ addV("person").property("name", "peter").property("age", 35).as('peter').
+ addE("knows").from("marko").to("vadas").property("weight", 0.5d).
+ addE("knows").from("marko").to("josh").property("weight", 1.0d).
+ addE("created").from("marko").to("lop").property("weight", 0.4d).
+ addE("created").from("josh").to("ripple").property("weight", 1.0d).
+ addE("created").from("josh").to("lop").property("weight", 0.4d).
+ addE("created").from("peter").to("lop").property("weight", 0.2d)
+ """
+ And using the parameter xx1 defined as "m[{\"t[label]\": \"self\", \"D[OUT]\":\"v[vadas]\", \"D[IN]\":\"v[vadas]\"}]"
+ And using the parameter xx2 defined as "m[{\"created\": \"N\"}]"
+ And the traversal of
+ """
+ g.inject(xx1, xx1, xx2).
+ fold().
+ mergeE(__.limit(Scope.local,1)).
+ option(Merge.onCreate, __.range(Scope.local, 1, 2)).
+ option(Merge.onMatch, __.tail(Scope.local))
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 6 for count of "g.V()"
+ And the graph should return 7 for count of "g.E()"
+ And the graph should return 7 for count of "g.E().hasNot(\"created\")"
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\").outE(\"knows\").hasNot(\"created\").inV().has(\"person\",\"name\",\"vadas\")"
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"vadas\").outE(\"self\").hasNot('weight').inV().has(\"person\",\"name\",\"vadas\")"
\ No newline at end of file
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
index 2aaa7b6..a9a61f4 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
@@ -654,9 +654,7 @@
option(Merge.onMatch, __.sideEffect(__.properties("age").drop()).select("m"))
"""
When iterated to list
- Then the result should have a count of 1
- And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\").has(\"age\", 19)"
- And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\").has(\"age\")"
+ Then the traversal will raise an error with message containing text of "The incoming traverser for MergeVertexStep cannot be an Element"
# onCreate inheritance from merge
@UserSuppliedVertexIds
@@ -1008,4 +1006,46 @@
g.mergeV([:]).option(Merge.onMatch, xx1)
"""
When iterated to list
- Then the traversal will raise an error with message containing text of "Property key can not be a hidden key: ~label"
\ No newline at end of file
+ Then the traversal will raise an error with message containing text of "Property key can not be a hidden key: ~label"
+
+ Scenario: g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_match
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29)
+ """
+ And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"marko\"}]"
+ And using the parameter xx2 defined as "m[{\"created\": \"N\"}]"
+ And the traversal of
+ """
+ g.inject(xx1, xx1, xx2).
+ fold().
+ mergeV(__.limit(Scope.local,1)).
+ option(Merge.onCreate, __.range(Scope.local, 1, 2)).
+ option(Merge.onMatch, __.tail(Scope.local))
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\").has(\"created\",\"N\")"
+ And the graph should return 1 for count of "g.V()"
+
+ Scenario: g_injectXlist1_list2X_mergeVXlimitXlocal_1XX_optionXonCreate_rangeXlocal_1_2X_optionXonMatch_tailXlocalXX_to_create
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29)
+ """
+ And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\"}]"
+ And using the parameter xx2 defined as "m[{\"created\": \"N\"}]"
+ And the traversal of
+ """
+ g.inject(xx1, xx1, xx2).
+ fold().
+ mergeV(__.limit(Scope.local,1)).
+ option(Merge.onCreate, __.range(Scope.local, 1, 2)).
+ option(Merge.onMatch, __.tail(Scope.local))
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"stephen\").hasNot(\"created\")"
+ And the graph should return 2 for count of "g.V()"
\ No newline at end of file