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 2022/01/24 19:15:48 UTC
[tinkerpop] branch TINKERPOP-2681 updated: added zero-arg mergeE/V()
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2681
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/TINKERPOP-2681 by this push:
new 7c39939 added zero-arg mergeE/V()
7c39939 is described below
commit 7c399397ca5200111538f3398f40039c77bc008b
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Mon Jan 24 14:15:26 2022 -0500
added zero-arg mergeE/V()
---
.../language/grammar/GremlinBaseVisitor.java | 10 +++++
.../language/grammar/TraversalMethodVisitor.java | 10 +++++
.../traversal/dsl/graph/GraphTraversal.java | 26 ++++++++++++
.../gremlin/process/traversal/dsl/graph/__.java | 14 +++++++
.../process/traversal/step/map/MergeEdgeStep.java | 5 +++
.../traversal/step/map/MergeVertexStep.java | 5 +++
.../Process/Traversal/GraphTraversal.cs | 18 ++++++++
.../src/Gremlin.Net/Process/Traversal/__.cs | 48 ++++++++++++++++++++++
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 2 +
.../gremlin-javascript/test/cucumber/gremlin.js | 2 +
gremlin-language/src/main/antlr4/Gremlin.g4 | 6 ++-
gremlin-python/src/main/python/radish/gremlin.py | 2 +
gremlin-test/features/map/MergeEdge.feature | 19 ++++++++-
gremlin-test/features/map/MergeVertex.feature | 18 ++++++++
14 files changed, 182 insertions(+), 3 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java
index e987683..8cc7807 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinBaseVisitor.java
@@ -1584,4 +1584,14 @@ public class GremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> implement
public T visitTraversalSourceSpawnMethod_mergeE_Traversal(final GremlinParser.TraversalSourceSpawnMethod_mergeE_TraversalContext ctx) {
notImplemented(ctx); return null;
}
+
+ @Override
+ public T visitTraversalMethod_mergeV_empty(final GremlinParser.TraversalMethod_mergeV_emptyContext ctx) {
+ notImplemented(ctx); return null;
+ }
+
+ @Override
+ public T visitTraversalMethod_mergeE_empty(final GremlinParser.TraversalMethod_mergeE_emptyContext ctx) {
+ notImplemented(ctx); return null;
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index c89ed86..e4eaa4d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -100,6 +100,16 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
}
@Override
+ public Traversal visitTraversalMethod_mergeV_empty(final GremlinParser.TraversalMethod_mergeV_emptyContext ctx) {
+ return this.graphTraversal.mergeV();
+ }
+
+ @Override
+ public Traversal visitTraversalMethod_mergeE_empty(final GremlinParser.TraversalMethod_mergeE_emptyContext ctx) {
+ return this.graphTraversal.mergeE();
+ }
+
+ @Override
public GraphTraversal visitTraversalMethod_mergeE_Map(final GremlinParser.TraversalMethod_mergeE_MapContext ctx) {
return this.graphTraversal.mergeE(GenericLiteralVisitor.getMapLiteral(ctx.genericLiteralMap()));
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 9b0bdc5..53eb732 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -1077,6 +1077,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
/**
+ * Performs a merge (i.e. upsert) style operation for an {@link Vertex} using the incoming {@code Map} traverser as
+ * an argument. The {@code Map} represents search criteria and will match each of the supplied key/value pairs where
+ * the keys may be {@code String} property values or a value of {@link T}. If a match is not made it will use that
+ * search criteria to create the new {@link Vertex}.
+ *
+ * @since 3.6.0
+ */
+ public default GraphTraversal<S, Vertex> mergeV() {
+ this.asAdmin().getBytecode().addStep(Symbols.mergeV);
+ final MergeVertexStep<S> step = new MergeVertexStep<>(this.asAdmin(), false);
+ return this.asAdmin().addStep(step);
+ }
+
+ /**
* Performs a merge (i.e. upsert) style operation for an {@link Vertex} using a {@code Map} as an argument.
* The {@code Map} represents search criteria and will match each of the supplied key/value pairs where the keys
* may be {@code String} property values or a value of {@link T}. If a match is not made it will use that search
@@ -1108,6 +1122,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
/**
+ * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using an
+ * incoming {@code Map} as an argument.
+ *
+ * @since 3.6.0
+ */
+ public default GraphTraversal<S, Edge> mergeE() {
+ this.asAdmin().getBytecode().addStep(Symbols.mergeE);
+ final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false);
+ return this.asAdmin().addStep(step);
+ }
+
+ /**
* Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
* {@code Map} as an argument.
*
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 01e5c0f..6e6374f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -516,6 +516,13 @@ public class __ {
}
/**
+ * @see GraphTraversal#mergeV()
+ */
+ public static <A> GraphTraversal<A, Vertex> mergeV() {
+ return __.<A>start().mergeV();
+ }
+
+ /**
* @see GraphTraversal#mergeV(Map)
*/
public static <A> GraphTraversal<A, Vertex> mergeV(final Map<Object, Object> searchCreate) {
@@ -544,6 +551,13 @@ public class __ {
}
/**
+ * @see GraphTraversal#mergeE()
+ */
+ public static <A> GraphTraversal<A, Edge> mergeE() {
+ return __.<A>start().mergeE();
+ }
+
+ /**
* @see GraphTraversal#mergeE(Map)
*/
public static <A> GraphTraversal<A, Edge> mergeE(final Map<?, Object> searchCreate) {
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 e5e4a19..ded688c 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
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
@@ -67,6 +68,10 @@ public class MergeEdgeStep<S> extends FlatMapStep<S, Edge> implements Mutating<E
private CallbackRegistry<Event> callbackRegistry;
+ public MergeEdgeStep(final Traversal.Admin traversal, final boolean isStart) {
+ this(traversal, isStart, new IdentityTraversal<>());
+ }
+
public MergeEdgeStep(final Traversal.Admin traversal, final boolean isStart, final Map<Object, Object> searchCreate) {
this(traversal, isStart, new ConstantTraversal<>(searchCreate));
}
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 365d83a..d000ca3 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
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
@@ -62,6 +63,10 @@ public class MergeVertexStep<S> extends FlatMapStep<S, Vertex> implements Mutati
protected CallbackRegistry<Event> callbackRegistry;
+ public MergeVertexStep(final Traversal.Admin traversal, final boolean isStart) {
+ this(traversal, isStart, new IdentityTraversal());
+ }
+
public MergeVertexStep(final Traversal.Admin traversal, final boolean isStart, final Map<Object, Object> searchCreate) {
this(traversal, isStart, new ConstantTraversal<>(searchCreate));
}
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 59ecb1a..03521f0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -1092,6 +1092,15 @@ namespace Gremlin.Net.Process.Traversal
/// <summary>
/// Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
/// </summary>
+ public GraphTraversal<S, Edge> MergeE ()
+ {
+ Bytecode.AddStep("mergeE");
+ return Wrap<S, Edge>(this);
+ }
+
+ /// <summary>
+ /// Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
public GraphTraversal<S, Edge> MergeE (IDictionary<object,object> m)
{
Bytecode.AddStep("mergeE", m);
@@ -1110,6 +1119,15 @@ namespace Gremlin.Net.Process.Traversal
/// <summary>
/// Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
/// </summary>
+ public GraphTraversal<S, Vertex> MergeV ()
+ {
+ Bytecode.AddStep("mergeV");
+ return Wrap<S, Vertex>(this);
+ }
+
+ /// <summary>
+ /// Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
public GraphTraversal<S, Vertex> MergeV (IDictionary<object,object> m)
{
Bytecode.AddStep("mergeV", m);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index acad588..62c19e0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -812,6 +812,54 @@ namespace Gremlin.Net.Process.Traversal
}
/// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeE step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, Edge> MergeE ()
+ {
+ return new GraphTraversal<object, Edge>().MergeE();
+ }
+
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeE step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, Edge> MergeE (IDictionary<object,object> m)
+ {
+ return new GraphTraversal<object, Edge>().MergeE(m);
+ }
+
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeE step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, Edge> MergeE (ITraversal t)
+ {
+ return new GraphTraversal<object, Edge>().MergeE(t);
+ }
+
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeV step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, Vertex> MergeV ()
+ {
+ return new GraphTraversal<object, Vertex>().MergeV();
+ }
+
+ /// <summary>
+ /// Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
+ public static GraphTraversal<object, Vertex> MergeV (IDictionary<object,object> m)
+ {
+ return new GraphTraversal<object, Vertex>().MergeV(m);
+ }
+
+ /// <summary>
+ /// Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
+ public static GraphTraversal<object, Vertex> MergeV (ITraversal t)
+ {
+ return new GraphTraversal<object, Vertex>().MergeV(t);
+ }
+
+ /// <summary>
/// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the min step to that traversal.
/// </summary>
public static GraphTraversal<object, E2> Min<E2>()
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 4ff7bbf..6a2f5ef 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -509,6 +509,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").As("a").AddV("person").Property(T.Id,101).Property("name","vadas").As("b").AddE("knows").From("a").To("b").Property("created","Y"), (g,p) =>g.MergeE((IDictionary<object,object>) p["xx1"]).Option(Merge.OnCreate, (IDic [...]
{"g_V_hasXperson_name_marko_X_mergeEXlabel_knowsX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").As("a").AddV("person").Property(T.Id,101).Property("name","vadas").As("b").AddE("knows").From("a").To("b").Property("created","Y").AddE("knows").From("a").To("b"), (g,p) =>g.V().Has("person","name","marko").Me [...]
{"g_VX100X_VX101X_mergeEXlabel_knows_out_marko_in_vadasX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko"), (g,p) =>g.V(100).V(101).MergeE((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V(), (g,p) =>g.E()}},
+ {"g_injectXlabel_knows_out_marko_in_vadasX_mergeE", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property(T.Id,100).Property("name","marko").AddV("person").Property(T.Id,101).Property("name","vadas"), (g,p) =>g.Inject(p["xx1"]).MergeE(), (g,p) =>g.V().Has("person","name","marko").Out("knows").Has("person","name","vadas")}},
{"g_mergeVXlabel_person_name_stephenX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V().Has("person","name","stephen")}},
{"g_mergeVXlabel_person_name_markoX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V().Has("person","name","marko")}},
{"g_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.MergeV((IDictionary<object,object>) p["xx1"]).Option(Merge.OnCreate, (IDictionary<object,object>) p["xx2"]), (g,p) =>g.V().Has("person","name","stephen").Has("age",19)}},
@@ -524,6 +525,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_injectX0X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.WithSideEffect("c",p["xx1"]).WithSideEffect("m",p["xx2"]).Inject(0).MergeV((IDictionary<object,object>) __.Select<object>("c")).Option(Merge.OnMatch, (IDictionary<object,ob [...]
{"g_injectX0X_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(0).MergeV((IDictionary<object,object>) p["xx1"]).Property("name","vadas","acl","public"), (g,p) =>g.V().Properties<object>("name").HasValue("vadas").Has("acl","public")}},
{"g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeVXidentityX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(p["xx1"],p["xx2"]).MergeV((IDictionary<object,object>) __.Identity()), (g,p) =>g.V().Has("person","name","stephen"), (g,p) =>g.V().Has("person","name","marko"), (g,p) =>g.V()}},
+ {"g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeV", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29).As("marko"), (g,p) =>g.Inject(p["xx1"],p["xx2"]).MergeV(), (g,p) =>g.V().Has("person","name","stephen"), (g,p) =>g.V().Has("person","name","marko"), (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-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 6af6338..2d6db86 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
@@ -498,6 +498,7 @@ const gremlins = {
g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated: [function({g, xx1, xx3, xx2}) { return g.addV("person").property(T.id,100).property("name","marko").as("a").addV("person").property(T.id,101).property("name","vadas").as("b").addE("knows").from_("a").to("b").property("created","Y") }, function({g, xx1, xx3, xx2}) { return g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3) }, function({g, xx1, xx3, xx2}) { retu [...]
g_V_hasXperson_name_marko_X_mergeEXlabel_knowsX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated: [function({g, xx1, xx3, xx2}) { return g.addV("person").property(T.id,100).property("name","marko").as("a").addV("person").property(T.id,101).property("name","vadas").as("b").addE("knows").from_("a").to("b").property("created","Y").addE("knows").from_("a").to("b") }, function({g, xx1, xx3, xx2}) { return g.V().has("person","name","marko").mergeE(xx1).option(Merge.onCre [...]
g_VX100X_VX101X_mergeEXlabel_knows_out_marko_in_vadasX: [function({g, xx1}) { return g.addV("person").property(T.id,100).property("name","marko") }, function({g, xx1}) { return g.V(100).V(101).mergeE(xx1) }, function({g, xx1}) { return g.V() }, function({g, xx1}) { return g.E() }],
+ g_injectXlabel_knows_out_marko_in_vadasX_mergeE: [function({g, xx1}) { return g.addV("person").property(T.id,100).property("name","marko").addV("person").property(T.id,101).property("name","vadas") }, function({g, xx1}) { return g.inject(xx1).mergeE() }, function({g, xx1}) { return g.V().has("person","name","marko").out("knows").has("person","name","vadas") }],
g_mergeVXlabel_person_name_stephenX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.mergeV(xx1) }, function({g, xx1}) { return g.V().has("person","name","stephen") }],
g_mergeVXlabel_person_name_markoX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.mergeV(xx1) }, function({g, xx1}) { return g.V().has("person","name","marko") }],
g_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.mergeV(xx1).option(Merge.onCreate,xx2) }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen").has("age",19) }],
@@ -513,6 +514,7 @@ const gremlins = {
g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_injectX0X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.withSideEffect("c",xx1).withSideEffect("m",xx2).inject(0).mergeV(__.select("c")).option(Merge.onMatch,__.select("m")) }, function({g, xx1, xx2}) { return g.V().has("person","name","marko").has("age",19) }],
g_injectX0X_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX: [function({g, xx1}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1}) { return g.inject(0).mergeV(xx1).property("name","vadas","acl","public") }, function({g, xx1}) { return g.V().properties("name").hasValue("vadas").has("acl","public") }],
g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeVXidentityX: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.inject(xx1,xx2).mergeV(__.identity()) }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen") }, function({g, xx1, xx2}) { return g.V().has("person","name","marko") }, function({g, xx1, xx2}) { return g.V() }],
+ g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeV: [function({g, xx1, xx2}) { return g.addV("person").property("name","marko").property("age",29).as("marko") }, function({g, xx1, xx2}) { return g.inject(xx1,xx2).mergeV() }, function({g, xx1, xx2}) { return g.V().has("person","name","stephen") }, function({g, xx1, xx2}) { return g.V().has("person","name","marko") }, 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-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 242b79c..7095e7b 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -287,12 +287,14 @@ traversalMethod_addV
;
traversalMethod_mergeV
- : 'mergeV' LPAREN genericLiteralMap RPAREN #traversalMethod_mergeV_Map
+ : 'mergeV' LPAREN RPAREN #traversalMethod_mergeV_empty
+ | 'mergeV' LPAREN genericLiteralMap RPAREN #traversalMethod_mergeV_Map
| 'mergeV' LPAREN nestedTraversal RPAREN #traversalMethod_mergeV_Traversal
;
traversalMethod_mergeE
- : 'mergeE' LPAREN genericLiteralMap RPAREN #traversalMethod_mergeE_Map
+ : 'mergeE' LPAREN RPAREN #traversalMethod_mergeE_empty
+ | 'mergeE' LPAREN genericLiteralMap RPAREN #traversalMethod_mergeE_Map
| 'mergeE' LPAREN nestedTraversal RPAREN #traversalMethod_mergeE_Traversal
;
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 8f9368d..16ee2a2 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -482,6 +482,7 @@ world.gremlins = {
'g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated': [(lambda g, xx1=None,xx3=None,xx2=None:g.addV('person').property(T.id_,100).property('name','marko').as_('a').addV('person').property(T.id_,101).property('name','vadas').as_('b').addE('knows').from_('a').to('b').property('created','Y')), (lambda g, xx1=None,xx3=None,xx2=None:g.mergeE(xx1).option(Merge.onCreate,xx2).option(Merge.onMatch,xx3)), (lambda g, xx1=None,xx3=None,xx [...]
'g_V_hasXperson_name_marko_X_mergeEXlabel_knowsX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists_updated': [(lambda g, xx1=None,xx3=None,xx2=None:g.addV('person').property(T.id_,100).property('name','marko').as_('a').addV('person').property(T.id_,101).property('name','vadas').as_('b').addE('knows').from_('a').to('b').property('created','Y').addE('knows').from_('a').to('b')), (lambda g, xx1=None,xx3=None,xx2=None:g.V().has('person','name','marko').mergeE(xx1).option(Merge. [...]
'g_VX100X_VX101X_mergeEXlabel_knows_out_marko_in_vadasX': [(lambda g, xx1=None:g.addV('person').property(T.id_,100).property('name','marko')), (lambda g, xx1=None:g.V(100).V(101).mergeE(xx1)), (lambda g, xx1=None:g.V()), (lambda g, xx1=None:g.E())],
+ 'g_injectXlabel_knows_out_marko_in_vadasX_mergeE': [(lambda g, xx1=None:g.addV('person').property(T.id_,100).property('name','marko').addV('person').property(T.id_,101).property('name','vadas')), (lambda g, xx1=None:g.inject(xx1).mergeE()), (lambda g, xx1=None:g.V().has('person','name','marko').out('knows').has('person','name','vadas'))],
'g_mergeVXlabel_person_name_stephenX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.mergeV(xx1)), (lambda g, xx1=None:g.V().has('person','name','stephen'))],
'g_mergeVXlabel_person_name_markoX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.mergeV(xx1)), (lambda g, xx1=None:g.V().has('person','name','marko'))],
'g_mergeVXlabel_person_name_stephenX_optionXonCreate_label_person_name_stephen_age_19X_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.mergeV(xx1).option(Merge.onCreate,xx2)), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen').has('age',19))],
@@ -497,6 +498,7 @@ world.gremlins = {
'g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_injectX0X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.withSideEffect('c',xx1).withSideEffect('m',xx2).inject(0).mergeV(__.select('c')).option(Merge.onMatch,__.select('m'))), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko').has('age',19))],
'g_injectX0X_mergeVXlabel_person_name_markoX_propertyXname_vadas_acl_publicX': [(lambda g, xx1=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None:g.inject(0).mergeV(xx1).property('name','vadas','acl','public')), (lambda g, xx1=None:g.V().properties('name').hasValue('vadas').has('acl','public'))],
'g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeVXidentityX': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.inject(xx1,xx2).mergeV(__.identity())), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen')), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko')), (lambda g, xx1=None,xx2=None:g.V())],
+ 'g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeV': [(lambda g, xx1=None,xx2=None:g.addV('person').property('name','marko').property('age',29).as_('marko')), (lambda g, xx1=None,xx2=None:g.inject(xx1,xx2).mergeV()), (lambda g, xx1=None,xx2=None:g.V().has('person','name','stephen')), (lambda g, xx1=None,xx2=None:g.V().has('person','name','marko')), (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/features/map/MergeEdge.feature b/gremlin-test/features/map/MergeEdge.feature
index 65173ce..a04ca40 100644
--- a/gremlin-test/features/map/MergeEdge.feature
+++ b/gremlin-test/features/map/MergeEdge.feature
@@ -181,4 +181,21 @@ Feature: Step - mergeE()
When iterated to list
Then the result should have a count of 0
And the graph should return 1 for count of "g.V()"
- And the graph should return 0 for count of "g.E()"
\ No newline at end of file
+ And the graph should return 0 for count of "g.E()"
+
+ @AllowUserSuppliedIds
+ Scenario: g_injectXlabel_knows_out_marko_in_vadasX_mergeE
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property(T.id, 100).property("name", "marko").
+ addV("person").property(T.id, 101).property("name", "vadas")
+ """
+ And using the parameter xx1 defined as "m[{\"t[label]\": \"knows\", \"D[OUT]\":\"v[100]\", \"D[IN]\":\"v[101]\"}]"
+ And the traversal of
+ """
+ g.inject(xx1).mergeE()
+ """
+ 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\").out(\"knows\").has(\"person\",\"name\",\"vadas\")"
\ No newline at end of file
diff --git a/gremlin-test/features/map/MergeVertex.feature b/gremlin-test/features/map/MergeVertex.feature
index 385f2f8..cda2e42 100644
--- a/gremlin-test/features/map/MergeVertex.feature
+++ b/gremlin-test/features/map/MergeVertex.feature
@@ -263,3 +263,21 @@ Feature: Step - mergeV()
And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"stephen\")"
And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\")"
And the graph should return 2 for count of "g.V()"
+
+ Scenario: g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeV
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).as("marko")
+ """
+ And using the parameter xx1 defined as "m[{\"t[label]\": \"person\", \"name\":\"marko\"}]"
+ And using the parameter xx2 defined as "m[{\"t[label]\": \"person\", \"name\":\"stephen\"}]"
+ And the traversal of
+ """
+ g.inject(xx1, xx2).mergeV()
+ """
+ When iterated to list
+ Then the result should have a count of 2
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"stephen\")"
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"marko\")"
+ And the graph should return 2 for count of "g.V()"
\ No newline at end of file