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/21 21:25:25 UTC
[tinkerpop] 01/01: wip
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
commit 780e720c6e4854e74f096b1973d3692efdfac499
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Jan 21 16:19:29 2022 -0500
wip
---
docs/src/dev/io/graphbinary.asciidoc | 5 ++
.../traversal/step/map/MergeVertexStep.java | 2 +-
.../traversal/translator/DotNetTranslator.java | 29 ++++++++++
.../traversal/translator/GroovyTranslator.java | 2 +-
.../gremlin/structure/io/binary/DataType.java | 1 +
.../io/binary/TypeSerializerRegistry.java | 2 +
.../structure/io/binary/types/EnumSerializer.java | 2 +
.../structure/io/graphson/GraphSONModule.java | 7 +++
.../Process/Traversal/GraphTraversal.cs | 46 ++++++++++++++++
.../Process/Traversal/GraphTraversalSource.cs | 54 +++++++++++++++++--
.../src/Gremlin.Net/Process/Traversal/Merge.cs | 63 ++++++++++++++++++++++
.../Structure/IO/GraphBinary/DataType.cs | 1 +
.../IO/GraphBinary/TypeSerializerRegistry.cs | 2 +
.../IO/GraphBinary/Types/EnumSerializer.cs | 6 +++
.../Structure/IO/GraphSON/GraphSONReader.cs | 1 +
.../Structure/IO/GraphSON/MergeDeserializer.cs | 36 +++++++++++++
.../Gherkin/CommonSteps.cs | 9 +++-
.../Gherkin/GherkinTestRunner.cs | 5 ++
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 51 +++++++++---------
.../Gherkin/IgnoreException.cs | 9 +++-
.../Structure/IO/GraphBinary/GraphBinaryTests.cs | 15 ++++++
.../Structure/IO/GraphSON/GraphSONReaderTests.cs | 12 +++++
.../Structure/IO/GraphSON/GraphSONWriterTests.cs | 13 ++++-
.../gremlin/driver/message/RequestMessage.java | 3 +-
.../lib/process/graph-traversal.js | 20 +++++++
.../test/cucumber/feature-steps.js | 8 ++-
.../gremlin-javascript/test/cucumber/gremlin.js | 3 +-
.../language/grammar/ReferenceGrammarTest.java | 2 +-
gremlin-python/build/generate.groovy | 2 +-
.../gremlin_python/process/graph_traversal.py | 38 +++++++++++++
.../python/gremlin_python/process/traversal.py | 5 ++
.../gremlin_python/structure/io/graphbinaryV1.py | 10 +++-
.../src/main/python/radish/feature_steps.py | 8 ++-
gremlin-python/src/main/python/radish/gremlin.py | 5 +-
.../tests/driver/test_driver_remote_connection.py | 1 +
.../tests/structure/io/test_graphbinaryV1.py | 7 ++-
.../handler/WsGremlinBinaryRequestDecoder.java | 1 +
.../handler/WsGremlinTextRequestDecoder.java | 1 +
gremlin-test/features/sideEffect/Group.feature | 22 ++++----
gremlin-test/features/sideEffect/Inject.feature | 7 ++-
.../tinkerpop/gremlin/features/StepDefinition.java | 5 +-
.../traversal/step/map/TinkerMergeVertexStep.java | 1 +
.../gremlin/tinkergraph/TinkerGraphWorld.java | 1 +
43 files changed, 454 insertions(+), 69 deletions(-)
diff --git a/docs/src/dev/io/graphbinary.asciidoc b/docs/src/dev/io/graphbinary.asciidoc
index 065370a..f3b0a82 100644
--- a/docs/src/dev/io/graphbinary.asciidoc
+++ b/docs/src/dev/io/graphbinary.asciidoc
@@ -107,6 +107,7 @@ Changes to existing types require new revision.
- `0x2b`: Tree
- `0x2c`: Metrics
- `0x2d`: TraversalMetrics
+- `0x2e`: Merge
- `0xfe`: Unspecified null object
- `0x00`: Custom
@@ -567,6 +568,10 @@ Where:
- `{duration}` is a `Long` describing the duration in nanoseconds.
- `{metrics}` is a `List` composed by `Metrics` items.
+==== Merge
+
+Format: a single `String` representing the enum value.
+
==== Custom
A custom type, represented as a blob value.
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 319db5d..365d83a 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
@@ -60,7 +60,7 @@ public class MergeVertexStep<S> extends FlatMapStep<S, Vertex> implements Mutati
private Traversal.Admin<S, Map<Object, Object>> onCreateTraversal = null;
private Traversal.Admin<S, Map<String, Object>> onMatchTraversal = null;
- private CallbackRegistry<Event> callbackRegistry;
+ protected CallbackRegistry<Event> callbackRegistry;
public MergeVertexStep(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/translator/DotNetTranslator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslator.java
index 5f3ae25..6bd3442 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslator.java
@@ -21,12 +21,14 @@ package org.apache.tinkerpop.gremlin.process.traversal.translator;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.Pick;
import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
import org.apache.tinkerpop.gremlin.process.traversal.Script;
import org.apache.tinkerpop.gremlin.process.traversal.TextP;
import org.apache.tinkerpop.gremlin.process.traversal.Translator;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
@@ -345,6 +347,33 @@ public final class DotNetTranslator implements Translator.ScriptTranslator {
script.append(", (").append(castSecondArgTo).append(") ");
convertToScript(instruction.getArguments()[1]);
script.append(",");
+ } else if (methodName.equals(GraphTraversal.Symbols.mergeE) || methodName.equals(GraphTraversal.Symbols.mergeV)) {
+ // there must be at least one argument - if null go with Map
+ final Object instArg = instruction.getArguments()[0];
+ if (null == instArg) {
+ script.append("(IDictionary<object,object>) null");
+ } else {
+ if (instArg instanceof Traversal) {
+ script.append("(ITraversal) ");
+ } else {
+ script.append("(IDictionary<object,object>) ");
+ }
+ convertToScript(instArg);
+ script.append(")");
+ }
+ } else if (methodName.equals(GraphTraversal.Symbols.option) &&
+ instruction.getArguments().length == 2 && instruction.getArguments()[0] instanceof Merge) {
+ final Object[] instArgs = instruction.getArguments();
+ // trying to catch option(Merge,Traversal|Map)
+ convertToScript(instArgs[0]);
+ script.append(", ");
+ if (instArgs[1] instanceof Traversal) {
+ script.append("(ITraversal) ");
+ } else {
+ script.append("(IDictionary<object,object>) ");
+ }
+ convertToScript(instArgs[1]);
+ script.append(")");
} else {
final Object[] instArgs = instruction.getArguments();
for (int idx = 0; idx < instArgs.length; idx++) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
index bfa3065..0143c27 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
@@ -174,7 +174,7 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
@Override
protected String getSyntax(final Pick o) {
- return "TraversalOptionParent.Pick." + o.toString();
+ return "Pick." + o.toString();
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
index 0159d4f..75b8060 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
@@ -70,6 +70,7 @@ public enum DataType {
TREE(0X2B),
METRICS(0x2C),
TRAVERSALMETRICS(0x2D),
+ MERGE(0x2E),
CHAR(0X80),
DURATION(0X81),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
index 0c4b913..4edcad2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.structure.io.binary;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Pick;
import org.apache.tinkerpop.gremlin.structure.io.binary.types.*;
import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
@@ -117,6 +118,7 @@ public class TypeSerializerRegistry {
new RegistryEntry<>(VertexProperty.Cardinality.class, EnumSerializer.CardinalitySerializer),
new RegistryEntry<>(Column.class, EnumSerializer.ColumnSerializer),
new RegistryEntry<>(Direction.class, EnumSerializer.DirectionSerializer),
+ new RegistryEntry<>(Merge.class, EnumSerializer.MergeSerializer),
new RegistryEntry<>(Operator.class, EnumSerializer.OperatorSerializer),
new RegistryEntry<>(Order.class, EnumSerializer.OrderSerializer),
new RegistryEntry<>(Pick.class, EnumSerializer.PickSerializer),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
index 52b4c08..41cf7fc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.structure.io.binary.types;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Pick;
import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
@@ -47,6 +48,7 @@ public class EnumSerializer<E extends Enum> extends SimpleTypeSerializer<E> {
public static final EnumSerializer<VertexProperty.Cardinality> CardinalitySerializer = new EnumSerializer<>(DataType.CARDINALITY, VertexProperty.Cardinality::valueOf);
public static final EnumSerializer<Column> ColumnSerializer = new EnumSerializer<>(DataType.COLUMN, Column::valueOf);
public static final EnumSerializer<Direction> DirectionSerializer = new EnumSerializer<>(DataType.DIRECTION, Direction::valueOf);
+ public static final EnumSerializer<Merge> MergeSerializer = new EnumSerializer<>(DataType.MERGE, Merge::valueOf);
public static final EnumSerializer<Operator> OperatorSerializer = new EnumSerializer<>(DataType.OPERATOR, Operator::valueOf);
public static final EnumSerializer<Order> OrderSerializer = new EnumSerializer<>(DataType.ORDER, Order::valueOf);
public static final EnumSerializer<Pick> PickSerializer = new EnumSerializer<>(DataType.PICK, Pick::valueOf);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index fccab3f..82d818f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.structure.io.graphson;
import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Operator;
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.P;
@@ -174,6 +175,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
VertexProperty.Cardinality.class,
Column.class,
Direction.class,
+ Merge.class,
Operator.class,
Order.class,
Pop.class,
@@ -257,6 +259,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
Stream.of(VertexProperty.Cardinality.class,
Column.class,
Direction.class,
+ Merge.class,
Operator.class,
Order.class,
Pop.class,
@@ -299,6 +302,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
Stream.of(VertexProperty.Cardinality.values(),
Column.values(),
Direction.values(),
+ Merge.values(),
Operator.values(),
Order.values(),
Pop.values(),
@@ -412,6 +416,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
VertexProperty.Cardinality.class,
Column.class,
Direction.class,
+ Merge.class,
Operator.class,
Order.class,
Pop.class,
@@ -491,6 +496,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
Stream.of(VertexProperty.Cardinality.class,
Column.class,
Direction.class,
+ Merge.class,
Operator.class,
Order.class,
Pop.class,
@@ -527,6 +533,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
Stream.of(VertexProperty.Cardinality.values(),
Column.values(),
Direction.values(),
+ Merge.values(),
Operator.values(),
Order.values(),
Pop.values(),
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index ebd1cdf..59ecb1a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -1090,6 +1090,43 @@ namespace Gremlin.Net.Process.Traversal
}
/// <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);
+ return Wrap<S, Edge>(this);
+ }
+
+ /// <summary>
+ /// Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
+ public GraphTraversal<S, Edge> MergeE (ITraversal t)
+ {
+ Bytecode.AddStep("mergeE", t);
+ return Wrap<S, Edge>(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);
+ return Wrap<S, Vertex>(this);
+ }
+
+ /// <summary>
+ /// Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
+ public GraphTraversal<S, Vertex> MergeV (ITraversal t)
+ {
+ Bytecode.AddStep("mergeV", t);
+ return Wrap<S, Vertex>(this);
+ }
+
+
+ /// <summary>
/// Adds the min step to this <see cref="GraphTraversal{SType, EType}" />.
/// </summary>
public GraphTraversal<S, E2> Min<E2> ()
@@ -1137,6 +1174,15 @@ namespace Gremlin.Net.Process.Traversal
/// <summary>
/// Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
/// </summary>
+ public GraphTraversal<S, E> Option (object pickToken, IDictionary<object,object> traversalOption)
+ {
+ Bytecode.AddStep("option", pickToken, traversalOption);
+ return Wrap<S, E>(this);
+ }
+
+ /// <summary>
+ /// Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
public GraphTraversal<S, E> Option (ITraversal traversalOption)
{
Bytecode.AddStep("option", traversalOption);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index ae5b1d9..5ad2f7d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -336,7 +336,7 @@ namespace Gremlin.Net.Process.Traversal
public GraphTraversal<Edge, Edge> AddE(string label)
{
var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
- traversal.Bytecode.AddStep("addE", label);
+ traversal.Bytecode.AddStep("addE", label);
return traversal;
}
@@ -347,7 +347,29 @@ namespace Gremlin.Net.Process.Traversal
public GraphTraversal<Edge, Edge> AddE(ITraversal edgeLabelTraversal)
{
var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
- traversal.Bytecode.AddStep("addE", edgeLabelTraversal);
+ traversal.Bytecode.AddStep("addE", edgeLabelTraversal);
+ return traversal;
+ }
+
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeE step to that
+ /// traversal.
+ /// </summary>
+ public GraphTraversal<Edge, Edge> MergeE(IDictionary<object,object> m)
+ {
+ var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
+ traversal.Bytecode.AddStep("mergeE", m);
+ return traversal;
+ }
+
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeE step to that
+ /// traversal.
+ /// </summary>
+ public GraphTraversal<Edge, Edge> MergeE(ITraversal t)
+ {
+ var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
+ traversal.Bytecode.AddStep("mergeE", t);
return traversal;
}
@@ -358,7 +380,7 @@ namespace Gremlin.Net.Process.Traversal
public GraphTraversal<Vertex, Vertex> AddV()
{
var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
- traversal.Bytecode.AddStep("addV");
+ traversal.Bytecode.AddStep("addV");
return traversal;
}
@@ -369,7 +391,7 @@ namespace Gremlin.Net.Process.Traversal
public GraphTraversal<Vertex, Vertex> AddV(string label)
{
var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
- traversal.Bytecode.AddStep("addV", label);
+ traversal.Bytecode.AddStep("addV", label);
return traversal;
}
@@ -380,7 +402,29 @@ namespace Gremlin.Net.Process.Traversal
public GraphTraversal<Vertex, Vertex> AddV(ITraversal vertexLabelTraversal)
{
var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
- traversal.Bytecode.AddStep("addV", vertexLabelTraversal);
+ traversal.Bytecode.AddStep("addV", vertexLabelTraversal);
+ return traversal;
+ }
+
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeV step to that
+ /// traversal.
+ /// </summary>
+ public GraphTraversal<Vertex, Vertex> MergeV(IDictionary<object,object> m)
+ {
+ var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
+ traversal.Bytecode.AddStep("mergeV", m);
+ return traversal;
+ }
+
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeV step to that
+ /// traversal.
+ /// </summary>
+ public GraphTraversal<Vertex, Vertex> MergeV(ITraversal t)
+ {
+ var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
+ traversal.Bytecode.AddStep("mergeV", t);
return traversal;
}
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Merge.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Merge.cs
new file mode 100644
index 0000000..b62fc8f
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Merge.cs
@@ -0,0 +1,63 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace Gremlin.Net.Process.Traversal
+{
+#pragma warning disable 1591
+
+ public class Merge : EnumWrapper, IFunction
+ {
+ private Merge(string enumValue)
+ : base("Merge", enumValue)
+ {
+ }
+
+ public static Merge OnCreate => new Merge("onCreate");
+
+ public static Merge OnMatch => new Merge("onMatch");
+
+ private static readonly IDictionary<string, Merge> Properties = new Dictionary<string, Merge>
+ {
+ { "onCreate", OnCreate },
+ { "onMatch", OnMatch },
+ };
+
+ /// <summary>
+ /// Gets the Merge enumeration by value.
+ /// </summary>
+ public static Merge GetByValue(string value)
+ {
+ if (!Properties.TryGetValue(value, out var property))
+ {
+ throw new ArgumentException($"No matching Merge for value '{value}'");
+ }
+ return property;
+ }
+ }
+
+
+#pragma warning restore 1591
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
index 3e65ad0..ee33cee 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
@@ -55,6 +55,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
public static readonly DataType Cardinality = new DataType(0x16);
public static readonly DataType Column = new DataType(0x17);
public static readonly DataType Direction = new DataType(0x18);
+ public static readonly DataType Merge = new DataType(0x2E);
public static readonly DataType Operator = new DataType(0x19);
public static readonly DataType Order = new DataType(0x1A);
public static readonly DataType Pick = new DataType(0x1B);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
index 87c28e6..d30b5ca 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
@@ -60,6 +60,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
{typeof(Cardinality), EnumSerializers.CardinalitySerializer},
{typeof(Column), EnumSerializers.ColumnSerializer},
{typeof(Direction), EnumSerializers.DirectionSerializer},
+ {typeof(Merge), EnumSerializers.MergeSerializer},
{typeof(Operator), EnumSerializers.OperatorSerializer},
{typeof(Order), EnumSerializers.OrderSerializer},
{typeof(Pick), EnumSerializers.PickSerializer},
@@ -107,6 +108,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
{DataType.Cardinality, EnumSerializers.CardinalitySerializer},
{DataType.Column, EnumSerializers.ColumnSerializer},
{DataType.Direction, EnumSerializers.DirectionSerializer},
+ {DataType.Merge, EnumSerializers.MergeSerializer},
{DataType.Operator, EnumSerializers.OperatorSerializer},
{DataType.Order, EnumSerializers.OrderSerializer},
{DataType.Pick, EnumSerializers.PickSerializer},
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
index d561c2a..5bc6080 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
@@ -58,6 +58,12 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
new EnumSerializer<Direction>(DataType.Direction, Direction.GetByValue);
/// <summary>
+ /// A serializer for <see cref="Merge"/> values.
+ /// </summary>
+ public static readonly EnumSerializer<Merge> MergeSerializer =
+ new EnumSerializer<Merge>(DataType.Merge, Merge.GetByValue);
+
+ /// <summary>
/// A serializer for <see cref="Operator"/> values.
/// </summary>
public static readonly EnumSerializer<Operator> OperatorSerializer =
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
index 16901bd..3208966 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
@@ -45,6 +45,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
{"g:Float", new FloatConverter()},
{"g:Double", new DoubleConverter()},
{"g:Direction", new DirectionDeserializer()},
+ {"g:Merge", new MergeDeserializer()},
{"g:UUID", new UuidDeserializer()},
{"g:Date", new DateDeserializer()},
{"g:Timestamp", new DateDeserializer()},
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
new file mode 100644
index 0000000..26b6869
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
@@ -0,0 +1,36 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Text.Json;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.Structure.IO.GraphSON
+{
+ internal class MergeDeserializer : IGraphSONDeserializer
+ {
+ public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
+ {
+ return Merge.GetByValue(graphsonObject.GetString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 03b429a..fcac51a 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -379,7 +379,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
private static Vertex ToVertex(string name, string graphName)
{
- return ScenarioData.GetByGraphName(graphName).Vertices[name];
+ if (ScenarioData.GetByGraphName(graphName).Vertices.ContainsKey(name))
+ {
+ return ScenarioData.GetByGraphName(graphName).Vertices[name];
+ }
+ else
+ {
+ return new Vertex(name);
+ }
}
private static Edge ToEdge(string name, string graphName)
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
index 0209c7b..365bedb 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -87,6 +87,11 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
},
{"g_V_properties_order", IgnoreReason.VertexPropertyNotSupportedInGherkin},
{"g_V_properties_order_id", IgnoreReason.VertexPropertyNotSupportedInGherkin},
+ {"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_injectX0X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option", IgnoreReason.MergeVEWithTraversalNotSupportedInTranslation},
+ {"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_mergeVXselectXcXX_optionXonMatch_selectXmXX_option", IgnoreReason.MergeVEWithTraversalNotSupportedInTranslation},
+ {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_injectX0X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option", IgnoreReason.MergeVEWithTraversalNotSupportedInTranslation},
+ {"g_injectXlabel_person_name_marko_label_person_name_stephenX_mergeVXidentityX", IgnoreReason.MergeVEWithTraversalNotSupportedInTranslation},
+ {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_mergeVXselectXcXX_optionXonCreate_selectXmXX_option", IgnoreReason.MergeVEWithTraversalNotSupportedInTranslation},
};
private static class Keywords
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index f89e2a5..4ff7bbf 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -500,30 +500,30 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Mean<object>()}},
{"g_injectXnull_10_20_nullX_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null,p["xx1"],p["xx2"],null).Mean<object>()}},
{"g_injectXlistXnull_10_20_nullXX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Mean<object>(Scope.Local)}},
- {"g_V_mergeEXlabel_self_weight_05X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.V().MergeE(p["xx1"]), (g,p) =>g.E().HasLabel("self").Has("weight",0.5)}},
- {"g_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").AddV("person").Property(T.Id,101).Property("name","vadas"), (g,p) =>g.MergeE(p["xx1"]), (g,p) =>g.V().Has("person","name","marko").Out("knows").Has("person","name","vadas")}},
- {"g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X_exists", 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"), (g,p) =>g.MergeE(p["xx1"]), (g,p) =>g.V().Has("person","name","marko").OutE("knows").Has("weight",0.5).InV().Has("person","name","vadas"), (g,p) =>g.V().Has("p [...]
- {"g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeE(p["xx1"]), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("weight",0.5)}},
- {"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeE(p["xx1"]).Option(Merge.OnCreate,p["xx2"]).Option(Merge.OnMatch,p["xx3"]), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("created","Y"), (g,p) =>g.E().HasLabel("knows").Has("created","N")}},
- {"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists", 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"), (g,p) =>g.MergeE(p["xx1"]).Option(Merge.OnCreate,p["xx2"]).Option(Merge.OnMatch,p["xx3"]), (g,p) =>g.V(), (g,p) =>g. [...]
- {"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(p["xx1"]).Option(Merge.OnCreate,p["xx2"]).Option(Merge.OnMatch,p["x [...]
- {"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(p["xx1"]), (g,p) =>g.V(), (g,p) =>g.E()}},
- {"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(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(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(p["xx1"]).Option(Merge.OnCreate,p["xx2"]), (g,p) =>g.V().Has("person","name","stephen").Has("age",19)}},
- {"g_mergeVXlabel_person_name_markoX_optionXonMatch_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(p["xx1"]).Option(Merge.OnMatch,p["xx2"]), (g,p) =>g.V().Has("person","name","marko").Has("age",19)}},
- {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_mergeVXselectXcXX_optionXonCreate_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"]).MergeV(__.Select<object>("c")).Option(Merge.OnCreate,__.Select<object>("m")), (g,p) =>g.V().Has [...]
- {"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_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"]).MergeV(__.Select<object>("c")).Option(Merge.OnMatch,__.Select<object>("m")), (g,p) =>g.V().Has("person","name","marko").Has( [...]
- {"g_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.MergeV(p["xx1"]).Property("name","vadas","acl","public"), (g,p) =>g.V().Properties<object>("name").HasValue("vadas").Has("acl","public")}},
- {"g_injectX0X_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.Inject(0).MergeV(p["xx1"]), (g,p) =>g.V().Has("person","name","stephen")}},
- {"g_injectX0X_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.Inject(0).MergeV(p["xx1"]), (g,p) =>g.V().Has("person","name","marko")}},
- {"g_injectX0X_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.Inject(0).MergeV(p["xx1"]).Option(Merge.OnCreate,p["xx2"]), (g,p) =>g.V().Has("person","name","stephen").Has("age",19)}},
- {"g_injectX0X_mergeVXlabel_person_name_markoX_optionXonMatch_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.Inject(0).MergeV(p["xx1"]).Option(Merge.OnMatch,p["xx2"]), (g,p) =>g.V().Has("person","name","marko").Has("age",19)}},
- {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_injectX0X_mergeVXselectXcXX_optionXonCreate_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(__.Select<object>("c")).Option(Merge.OnCreate,__.Select<object>("m") [...]
- {"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(__.Select<object>("c")).Option(Merge.OnMatch,__.Select<object>("m")), (g,p) =>g.V().Has("person", [...]
- {"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(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(__.Identity()), (g,p) =>g.V().Has("person","name","stephen"), (g,p) =>g.V().Has("person","name","marko"), (g,p) =>g.V()}},
+ {"g_V_mergeEXlabel_self_weight_05X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","marko").Property("age",29), (g,p) =>g.V().MergeE((IDictionary<object,object>) p["xx1"]), (g,p) =>g.E().HasLabel("self").Has("weight",0.5)}},
+ {"g_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").AddV("person").Property(T.Id,101).Property("name","vadas"), (g,p) =>g.MergeE((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V().Has("person","name","marko").Out("knows").Has("person","name","vadas")}},
+ {"g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X_exists", 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"), (g,p) =>g.MergeE((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V().Has("person","name","marko").OutE("knows").Has("weight",0.5).InV().Has("person","name"," [...]
+ {"g_mergeEXlabel_knows_out_marko_in_vadas_weight_05X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeE((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("weight",0.5)}},
+ {"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.MergeE((IDictionary<object,object>) p["xx1"]).Option(Merge.OnCreate, (IDictionary<object,object>) p["xx2"]).Option(Merge.OnMatch, (IDictionary<object,object>) p["xx3"]), (g,p) =>g.V(), (g,p) =>g.E().HasLabel("knows").Has("created","Y"), (g,p) =>g.E().HasLabel("knows").Has("created","N")}},
+ {"g_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_created_YX_optionXonMatch_created_NX_exists", 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"), (g,p) =>g.MergeE((IDictionary<object,object>) p["xx1"]).Option(Merge.OnCreate, (IDictionary<object,object>) p["xx2"] [...]
+ {"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_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)}},
+ {"g_mergeVXlabel_person_name_markoX_optionXonMatch_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.OnMatch, (IDictionary<object,object>) p["xx2"]), (g,p) =>g.V().Has("person","name","marko").Has("age",19)}},
+ {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_mergeVXselectXcXX_optionXonCreate_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"]).MergeV((IDictionary<object,object>) __.Select<object>("c")).Option(Merge.OnCreate, (IDictionary [...]
+ {"g_withSideEffectXc_label_person_name_markoX_withSideEffectXm_age_19X_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"]).MergeV((IDictionary<object,object>) __.Select<object>("c")).Option(Merge.OnMatch, (IDictionary<object,object>) __.Select<obj [...]
+ {"g_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.MergeV((IDictionary<object,object>) p["xx1"]).Property("name","vadas","acl","public"), (g,p) =>g.V().Properties<object>("name").HasValue("vadas").Has("acl","public")}},
+ {"g_injectX0X_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.Inject(0).MergeV((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V().Has("person","name","stephen")}},
+ {"g_injectX0X_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.Inject(0).MergeV((IDictionary<object,object>) p["xx1"]), (g,p) =>g.V().Has("person","name","marko")}},
+ {"g_injectX0X_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.Inject(0).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)}},
+ {"g_injectX0X_mergeVXlabel_person_name_markoX_optionXonMatch_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.Inject(0).MergeV((IDictionary<object,object>) p["xx1"]).Option(Merge.OnMatch, (IDictionary<object,object>) p["xx2"]), (g,p) =>g.V().Has("person","name","marko").Has("age",19)}},
+ {"g_withSideEffectXc_label_person_name_stephenX_withSideEffectXm_label_person_name_stephen_age_19X_injectX0X_mergeVXselectXcXX_optionXonCreate_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.On [...]
+ {"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_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>()}},
@@ -831,7 +831,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_outXfollowedByX_group_byXsongTypeX_byXbothE_group_byXlabelX_byXweight_sumXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("followedBy").Group<object,object>().By("songType").By(__.BothE().Group<object,object>().By(T.Label).By(__.Values<object>("weight").Sum<object>()))}},
{"g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group("m").By("name").By(__.In("knows").Values<object>("name")).Cap<object>("m")}},
{"g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By(T.Label).By(__.BothE().Group("a").By(T.Label).By(__.Values<object>("weight").Sum<object>()).Values<object>("weight").Sum<object>())}},
- {"g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSideEffect("a",p["xx1"]).V().Group("a").By("name").By(__.OutE().Label().Fold()).Cap<object>("a").Unfold<object>().Group<object,object>().By(Column.Keys).By(__.Select<object>(Column.Values).Order(Scope.Local).By(Order.Asc))}},
{"g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").As("p").Out("created").Group<object,object>().By("name").By(__.Select<object>("p").Values<object>("age").Sum<object>())}},
{"g_V_hasLabelXpersonX_asXpX_outXcreatedX_groupXaX_byXnameX_byXselectXpX_valuesXageX_sumX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").As("p").Out("created").Group("a").By("name").By(__.Select<object>("p").Values<object>("age").Sum<object>()).Cap<object>("a")}},
{"g_V_group_byXlabelX_byXlabel_countX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By(__.Label()).By(__.Label().Count())}},
@@ -854,7 +853,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("person","name","marko").Both("knows").GroupCount<object>().By(__.Values<object>("name").Fold())}},
{"g_VX1X_out_injectXv2X_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().Inject((Vertex) p["v2"]).Values<object>("name")}},
{"g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().Values<object>("name").Inject("daniel").As("a").Map<object>((IFunction) p["l1"]).Path()}},
- {"g_VX1X_injectXg_VX4XX_out_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Inject((Vertex) p["v4"]).Out().Values<object>("name")}},
+ {"g_VX1X_injectXg_VX4XX_out_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Inject((Vertex) p["v2"]).Out().Values<object>("name")}},
{"g_injectXnull_1_3_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null,1,3,null)}},
{"g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(10,20,null,20,10,10).GroupCount("x").Dedup().As("y").Project<object>("a","b").By().By(__.Select<object>("x").Select<object>(__.Select<object>("y")))}},
{"g_injectXname_marko_age_nullX_selectXname_ageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Select<object>("name","age")}},
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
index 2fa881b..8f1bbac 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
@@ -70,6 +70,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
/// <summary>
/// Need a Gherkin parser for VertexProperty results: https://issues.apache.org/jira/browse/TINKERPOP-2686
/// </summary>
- VertexPropertyNotSupportedInGherkin
+ VertexPropertyNotSupportedInGherkin,
+
+ /// <summary>
+ /// VarAsBindingASTTransformation isn't capable of properly casting arguments so the DotNetTranslator can't
+ /// produce the right Gremlin. These tests could be static translated but there are a lot of them so it would
+ /// be better to solve this more directly.
+ /// </summary>
+ MergeVEWithTraversalNotSupportedInTranslation
}
}
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
index 7978005..eecb385 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
@@ -535,6 +535,21 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
Assert.Equal(expected, actual);
}
+
+ [Fact]
+ public async Task TestMerge()
+ {
+ var expected = Merge.OnCreate;
+ var writer = CreateGraphBinaryWriter();
+ var reader = CreateGraphBinaryReader();
+ var serializationStream = new MemoryStream();
+
+ await writer.WriteAsync(expected, serializationStream);
+ serializationStream.Position = 0;
+ var actual = await reader.ReadAsync(serializationStream);
+
+ Assert.Equal(expected, actual);
+ }
[Fact]
public async Task TestOperator()
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
index 5bc232b..2c33a1e 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
@@ -312,6 +312,18 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
Assert.Equal(Direction.Out, deserializedValue);
}
+
+ [Theory, MemberData(nameof(Versions))]
+ public void ShouldDeserializeMerge(int version)
+ {
+ const string serializedValue = "{\"@type\":\"g:Merge\",\"@value\":\"onMatch\"}";
+ var reader = CreateStandardGraphSONReader(version);
+
+ var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
+ var deserializedValue = reader.ToObject(jsonElement);
+
+ Assert.Equal(Merge.OnMatch, deserializedValue);
+ }
[Fact]
public void ShouldDeserializePathFromGraphSON2()
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
index ce593f7..9247831 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
@@ -258,7 +258,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
}
[Theory, MemberData(nameof(Versions))]
- public void ShouldSerializeEnum(int version)
+ public void ShouldSerializeDirection(int version)
{
var writer = CreateGraphSONWriter(version);
@@ -269,6 +269,17 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
}
[Theory, MemberData(nameof(Versions))]
+ public void ShouldSerializeMerge(int version)
+ {
+ var writer = CreateGraphSONWriter(version);
+
+ var serializedEnum = writer.WriteObject(Merge.OnMatch);
+
+ var expectedGraphSON = "{\"@type\":\"g:Merge\",\"@value\":\"onMatch\"}";
+ Assert.Equal(expectedGraphSON, serializedEnum);
+ }
+
+ [Theory, MemberData(nameof(Versions))]
public void ShouldSerializeList(int version)
{
var writer = CreateGraphSONWriter(version);
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/RequestMessage.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/RequestMessage.java
index dc10baf..aeebf35 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/RequestMessage.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/RequestMessage.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.driver.message;
+import org.apache.tinkerpop.gremlin.driver.Tokens;
import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
import java.util.HashMap;
@@ -34,7 +35,7 @@ public final class RequestMessage {
/**
* An "invalid" message. Used internally only.
*/
- public static final RequestMessage INVALID = new RequestMessage("invalid");
+ public static final RequestMessage INVALID = new RequestMessage(Tokens.OPS_INVALID);
private final UUID requestId;
private final String op;
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index c609ba0..ae3d7f3 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -212,6 +212,16 @@ class GraphTraversalSource {
const b = new Bytecode(this.bytecode).addStep('addE', args);
return new this.graphTraversalClass(this.graph, new TraversalStrategies(this.traversalStrategies), b);
}
+
+ /**
+ * mergeV GraphTraversalSource step method.
+ * @param {...Object} args
+ * @returns {GraphTraversal}
+ */
+ mergeE(...args) {
+ const b = new Bytecode(this.bytecode).addStep('mergeE', args);
+ return new this.graphTraversalClass(this.graph, new TraversalStrategies(this.traversalStrategies), b);
+ }
/**
* addV GraphTraversalSource step method.
@@ -222,6 +232,16 @@ class GraphTraversalSource {
const b = new Bytecode(this.bytecode).addStep('addV', args);
return new this.graphTraversalClass(this.graph, new TraversalStrategies(this.traversalStrategies), b);
}
+
+ /**
+ * mergeV GraphTraversalSource step method.
+ * @param {...Object} args
+ * @returns {GraphTraversal}
+ */
+ mergeV(...args) {
+ const b = new Bytecode(this.bytecode).addStep('mergeV', args);
+ return new this.graphTraversalClass(this.graph, new TraversalStrategies(this.traversalStrategies), b);
+ }
/**
* inject GraphTraversalSource step method.
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index d500feb..ba23650 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -273,7 +273,13 @@ function toNumeric(stringValue) {
}
function toVertex(name) {
- return this.getData().vertices.get(name);
+ // some vertices are cached, like those from toy graphs but some are just references. if they are
+ // not cached then they are meant to be references.
+ const vertices = this.getData().vertices;
+ if (vertices.has(name))
+ return this.getData().vertices.get(name);
+ else
+ return new graphModule.Vertex(name, "vertex")
}
function toVertexId(name) {
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 6079579..6af6338 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
@@ -820,7 +820,6 @@ const gremlins = {
g_V_outXfollowedByX_group_byXsongTypeX_byXbothE_group_byXlabelX_byXweight_sumXX: [function({g}) { return g.V().out("followedBy").group().by("songType").by(__.bothE().group().by(T.label).by(__.values("weight").sum())) }],
g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX: [function({g}) { return g.V().group("m").by("name").by(__.in_("knows").values("name")).cap("m") }],
g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX: [function({g}) { return g.V().group().by(T.label).by(__.bothE().group("a").by(T.label).by(__.values("weight").sum()).values("weight").sum()) }],
- g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX: [function({g, xx1}) { return g.withSideEffect("a",xx1).V().group("a").by("name").by(__.outE().label().fold()).cap("a").unfold().group().by(Column.keys).by(__.select(Column.values).order(Scope.local).by(Order.asc)) }],
g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX: [function({g}) { return g.V().hasLabel("person").as("p").out("created").group().by("name").by(__.select("p").values("age").sum()) }],
g_V_hasLabelXpersonX_asXpX_outXcreatedX_groupXaX_byXnameX_byXselectXpX_valuesXageX_sumX_capXaX: [function({g}) { return g.V().hasLabel("person").as("p").out("created").group("a").by("name").by(__.select("p").values("age").sum()).cap("a") }],
g_V_group_byXlabelX_byXlabel_countX: [function({g}) { return g.V().group().by(__.label()).by(__.label().count()) }],
@@ -843,7 +842,7 @@ const gremlins = {
g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX: [function({g}) { return g.V().has("person","name","marko").both("knows").groupCount().by(__.values("name").fold()) }],
g_VX1X_out_injectXv2X_name: [function({g, vid1, v2}) { return g.V(vid1).out().inject(v2).values("name") }],
g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path: [function({g, l1, vid1}) { return g.V(vid1).out().values("name").inject("daniel").as("a").map(l1).path() }],
- g_VX1X_injectXg_VX4XX_out_name: [function({g, vid1, v4}) { return g.V(vid1).inject(v4).out().values("name") }],
+ g_VX1X_injectXg_VX4XX_out_name: [function({g, vid1, v2}) { return g.V(vid1).inject(v2).out().values("name") }],
g_injectXnull_1_3_nullX: [function({g}) { return g.inject(null,1,3,null) }],
g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX: [function({g}) { return g.inject(10,20,null,20,10,10).groupCount("x").dedup().as("y").project("a","b").by().by(__.select("x").select(__.select("y"))) }],
g_injectXname_marko_age_nullX_selectXname_ageX: [function({g, xx1}) { return g.inject(xx1).select("name","age") }],
diff --git a/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java b/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
index a0e91fe..b241c59 100644
--- a/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
+++ b/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
@@ -70,7 +70,7 @@ public class ReferenceGrammarTest extends AbstractGrammarTest {
return String.format("[%s]", listItems);
}));
add(Pair.with(Pattern.compile("v\\[(.+)\\]"), (k,v) -> "\"1\""));
- add(Pair.with(Pattern.compile("v(\\d)"), (k,v) -> String.format("new Vertex(%s)", v)));
+ add(Pair.with(Pattern.compile("v(\\d)"), (k,v) -> String.format("new Vertex(%s, \"vertex\")", v)));
add(Pair.with(Pattern.compile("e\\[(.+)\\]"), (k,v) -> "\"1\""));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.?.*"), (k,v) -> v));
add(Pair.with(Pattern.compile("m\\[(.*)\\]"), (k,v) -> v.replace('{','[').replace('}', ']')));
diff --git a/gremlin-python/build/generate.groovy b/gremlin-python/build/generate.groovy
index a633cd7..0c6dd42 100644
--- a/gremlin-python/build/generate.groovy
+++ b/gremlin-python/build/generate.groovy
@@ -87,7 +87,7 @@ radishGremlinFile.withWriter('UTF-8') { Writer writer ->
'from gremlin_python.process.traversal import TraversalStrategy\n' +
'from gremlin_python.process.graph_traversal import __\n' +
'from gremlin_python.structure.graph import Graph\n' +
- 'from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO, WithOptions\n')
+ 'from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, Merge, T, Pick, Operator, IO, WithOptions\n')
// Groovy can't process certain null oriented calls because it gets confused with the right overload to call
// at runtime. using this approach for now as these are the only such situations encountered so far. a better
diff --git a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
index 525bc9d..c8e8ae4 100644
--- a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
@@ -144,6 +144,16 @@ class GraphTraversalSource(object):
traversal.bytecode.add_step("addV", *args)
return traversal
+ def mergeV(self, *args):
+ traversal = self.get_graph_traversal()
+ traversal.bytecode.add_step("mergeV", *args)
+ return traversal
+
+ def mergeE(self, *args):
+ traversal = self.get_graph_traversal()
+ traversal.bytecode.add_step("mergeE", *args)
+ return traversal
+
def inject(self, *args):
traversal = self.get_graph_traversal()
traversal.bytecode.add_step("inject", *args)
@@ -401,6 +411,14 @@ class GraphTraversal(Traversal):
self.bytecode.add_step("mean", *args)
return self
+ def mergeE(self, *args):
+ self.bytecode.add_step("mergeE", *args)
+ return self
+
+ def mergeV(self, *args):
+ self.bytecode.add_step("mergeV", *args)
+ return self
+
def min_(self, *args):
self.bytecode.add_step("min", *args)
return self
@@ -827,6 +845,14 @@ class __(object, metaclass=MagicType):
return cls.graph_traversal(None, None, Bytecode()).mean(*args)
@classmethod
+ def mergeE(cls, *args):
+ return cls.graph_traversal(None, None, Bytecode()).mergeE(*args)
+
+ @classmethod
+ def mergeV(cls, *args):
+ return cls.graph_traversal(None, None, Bytecode()).mergeV(*args)
+
+ @classmethod
def min_(cls, *args):
return cls.graph_traversal(None, None, Bytecode()).min_(*args)
@@ -1254,6 +1280,14 @@ def mean(*args):
return __.mean(*args)
+def mergeE(*args):
+ return __.mergeE(*args)
+
+
+def mergeV(*args):
+ return __.mergeV(*args)
+
+
def min_(*args):
return __.min_(*args)
@@ -1514,6 +1548,10 @@ statics.add_static('max_', max_)
statics.add_static('mean', mean)
+statics.add_static('mergeE', mergeE)
+
+statics.add_static('mergeV', mergeV)
+
statics.add_static('min_', min_)
statics.add_static('not_', not_)
diff --git a/gremlin-python/src/main/python/gremlin_python/process/traversal.py b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
index f7bd31d..e24948c 100644
--- a/gremlin-python/src/main/python/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
@@ -152,6 +152,11 @@ GryoVersion = Enum('GryoVersion', ' V1_0 V3_0')
statics.add_static('V1_0', GryoVersion.V1_0)
statics.add_static('V3_0', GryoVersion.V3_0)
+Merge = Enum('Merge', ' onCreate onMatch')
+
+statics.add_static('onCreate', Merge.onCreate)
+statics.add_static('onMatch', Merge.onMatch)
+
Order = Enum('Order', ' asc desc shuffle')
statics.add_static('shuffle', Order.shuffle)
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
index a5a258a..f39197a 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
@@ -33,8 +33,8 @@ from datetime import timedelta
from gremlin_python import statics
from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, \
SingleByte, ByteBufferType, GremlinType, SingleChar
-from gremlin_python.process.traversal import Barrier, Binding, Bytecode, Cardinality, Column, Direction, Operator, \
- Order, Pick, Pop, P, Scope, TextP, Traversal, Traverser, \
+from gremlin_python.process.traversal import Barrier, Binding, Bytecode, Cardinality, Column, Direction, Merge, \
+ Operator, Order, Pick, Pop, P, Scope, TextP, Traversal, Traverser, \
TraversalStrategy, T
from gremlin_python.process.graph_traversal import GraphTraversal
from gremlin_python.structure.graph import Graph, Edge, Property, Vertex, VertexProperty, Path
@@ -96,6 +96,7 @@ class DataType(Enum):
tree = 0x2b # not supported - no tree object in Python yet
metrics = 0x2c
traversalmetrics = 0x2d
+ merge = 0x2e
char = 0x80
duration = 0x81
inetaddress = 0x82 # todo
@@ -850,6 +851,11 @@ class PSerializer(_GraphBinaryTypeIO):
return to_extend
+class MergeIO(_EnumIO):
+ graphbinary_type = DataType.merge
+ python_type = Merge
+
+
class ScopeIO(_EnumIO):
graphbinary_type = DataType.scope
python_type = Scope
diff --git a/gremlin-python/src/main/python/radish/feature_steps.py b/gremlin-python/src/main/python/radish/feature_steps.py
index 66bfc45..6d0a72d 100644
--- a/gremlin-python/src/main/python/radish/feature_steps.py
+++ b/gremlin-python/src/main/python/radish/feature_steps.py
@@ -20,7 +20,7 @@
import json
import re
from gremlin_python.statics import long
-from gremlin_python.structure.graph import Path
+from gremlin_python.structure.graph import Path, Vertex
from gremlin_python.process.anonymous_traversal import traversal
from gremlin_python.process.graph_traversal import __
from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO, WithOptions
@@ -221,7 +221,11 @@ def __find_cached_element(ctx, graph_name, identifier, element_type):
else:
cache = ctx.lookup_v[graph_name] if element_type == "v" else ctx.lookup_e[graph_name]
- return cache[identifier]
+ # try to lookup the element - if it can't be found then it must be a reference Vertex
+ if identifier in cache:
+ return cache[identifier]
+ else:
+ return Vertex(identifier)
def _convert_results(val):
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 7f4a084..8f9368d 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -29,7 +29,7 @@ from gremlin_python.process.anonymous_traversal import traversal
from gremlin_python.process.traversal import TraversalStrategy
from gremlin_python.process.graph_traversal import __
from gremlin_python.structure.graph import Graph
-from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO, WithOptions
+from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, Merge, T, Pick, Operator, IO, WithOptions
world.gremlins = {
'g_V_branchXlabel_eq_person__a_bX_optionXa__ageX_optionXb__langX_optionXb__nameX': [(lambda g, l1=None:g.V().branch(l1).option('a',__.age).option('b',__.lang).option('b',__.name))],
@@ -804,7 +804,6 @@ world.gremlins = {
'g_V_outXfollowedByX_group_byXsongTypeX_byXbothE_group_byXlabelX_byXweight_sumXX': [(lambda g:g.V().out('followedBy').group().by('songType').by(__.bothE().group().by(T.label).by(__.weight.sum_())))],
'g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX': [(lambda g:g.V().group('m').by('name').by(__.in_('knows').name).cap('m'))],
'g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX': [(lambda g:g.V().group().by(T.label).by(__.bothE().group('a').by(T.label).by(__.weight.sum_()).weight.sum_()))],
- 'g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX': [(lambda g, xx1=None:g.withSideEffect('a',xx1).V().group('a').by('name').by(__.outE().label().fold()).cap('a').unfold().group().by(Column.keys).by(__.select(Column.values).order(Scope.local).by(Order.asc)))],
'g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX': [(lambda g:g.V().hasLabel('person').as_('p').out('created').group().by('name').by(__.select('p').age.sum_()))],
'g_V_hasLabelXpersonX_asXpX_outXcreatedX_groupXaX_byXnameX_byXselectXpX_valuesXageX_sumX_capXaX': [(lambda g:g.V().hasLabel('person').as_('p').out('created').group('a').by('name').by(__.select('p').age.sum_()).cap('a'))],
'g_V_group_byXlabelX_byXlabel_countX': [(lambda g:g.V().group().by(__.label()).by(__.label().count()))],
@@ -827,7 +826,7 @@ world.gremlins = {
'g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX': [(lambda g:g.V().has('person','name','marko').both('knows').groupCount().by(__.name.fold()))],
'g_VX1X_out_injectXv2X_name': [(lambda g, vid1=None,v2=None:g.V(vid1).out().inject(v2).name)],
'g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path': [(lambda g, l1=None,vid1=None:g.V(vid1).out().name.inject('daniel').as_('a').map(l1).path())],
- 'g_VX1X_injectXg_VX4XX_out_name': [(lambda g, vid1=None,v4=None:g.V(vid1).inject(v4).out().name)],
+ 'g_VX1X_injectXg_VX4XX_out_name': [(lambda g, vid1=None,v2=None:g.V(vid1).inject(v2).out().name)],
'g_injectXnull_1_3_nullX': [(lambda g:g.inject(None,1,3,None))],
'g_injectX10_20_null_20_10_10X_groupCountXxX_dedup_asXyX_projectXa_bX_by_byXselectXxX_selectXselectXyXXX': [(lambda g:g.inject(10,20,None,20,10,10).groupCount('x').dedup().as_('y').project('a','b').by().by(__.select('x').select(__.select('y'))))],
'g_injectXname_marko_age_nullX_selectXname_ageX': [(lambda g, xx1=None:g.inject(xx1).select('name','age'))],
diff --git a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
index c931bc9..14b9577 100644
--- a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
@@ -44,6 +44,7 @@ class TestDriverRemoteConnection(object):
assert long(6) == g.V().count().toList()[0]
# #
assert Vertex(1) == g.V(1).next()
+ assert Vertex(1) == g.V(Vertex(1)).next()
assert 1 == g.V(1).id_().next()
assert Traverser(Vertex(1)) == g.V(1).nextTraverser()
assert 1 == len(g.V(1).toList())
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py b/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py
index 2f2b211..b12c48a 100644
--- a/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py
+++ b/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py
@@ -24,7 +24,7 @@ import math
from gremlin_python.statics import timestamp, long, SingleByte, SingleChar, ByteBufferType
from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Path
from gremlin_python.structure.io.graphbinaryV1 import GraphBinaryWriter, GraphBinaryReader
-from gremlin_python.process.traversal import Barrier, Binding, Bytecode
+from gremlin_python.process.traversal import Barrier, Binding, Bytecode, Merge
class TestGraphBinaryReader(object):
@@ -166,6 +166,11 @@ class TestGraphSONWriter(object):
output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
assert x == output
+ def test_merge(self):
+ x = Merge.onMatch
+ output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+ assert x == output
+
def test_binding(self):
x = Binding("name", "marko")
output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java
index b05ae92..3af49f4 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinBinaryRequestDecoder.java
@@ -76,6 +76,7 @@ public class WsGremlinBinaryRequestDecoder extends MessageToMessageDecoder<Binar
try {
objects.add(serializer.deserializeRequest(messageBytes.discardReadBytes()));
} catch (SerializationException se) {
+ logger.warn(se.getMessage());
objects.add(RequestMessage.INVALID);
}
} finally {
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java
index 50dc6f3..84b0888 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinTextRequestDecoder.java
@@ -63,6 +63,7 @@ public class WsGremlinTextRequestDecoder extends MessageToMessageDecoder<TextWeb
objects.add(serializer.deserializeRequest(frame.text()));
} catch (SerializationException se) {
+ logger.warn(se.getMessage());
objects.add(RequestMessage.INVALID);
}
}
diff --git a/gremlin-test/features/sideEffect/Group.feature b/gremlin-test/features/sideEffect/Group.feature
index b8e7b5c..01a5a21 100644
--- a/gremlin-test/features/sideEffect/Group.feature
+++ b/gremlin-test/features/sideEffect/Group.feature
@@ -264,17 +264,17 @@ Feature: Step - group()
| m[{"software":"d[2.0].d", "person":"d[5.0].d"}] |
# The post-ordering really isn't really right but works around TINKERPOP-2600
- Scenario: g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX
- Given the modern graph
- And using the parameter xx1 defined as "m[{\"marko\":l[\"666\"], \"noone\":l[\"blah\"]}]"
- And the traversal of
- """
- g.withSideEffect("a", xx1).V().group("a").by("name").by(__.outE().label().fold()).cap("a").unfold().group().by(keys).by(select(values).order(Scope.local).by(Order.asc))
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | m[{"ripple":[], "peter":["created"], "noone":["blah"], "vadas":[], "josh":["created", "created"], "lop":[], "marko":["666", "created", "knows", "knows"]}] |
+# Scenario: g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX
+# Given the modern graph
+# And using the parameter xx1 defined as "m[{\"marko\":\"l[\"666\"]\", \"noone\":\"l[\"blah\"]\"}]"
+# And the traversal of
+# """
+# g.withSideEffect("a", xx1).V().group("a").by("name").by(__.outE().label().fold()).cap("a").unfold().group().by(Column.keys).by(select(Column.values).order(Scope.local).by(Order.asc))
+# """
+# When iterated to list
+# Then the result should be unordered
+# | result |
+# | m[{"ripple":[], "peter":["created"], "noone":["blah"], "vadas":[], "josh":["created", "created"], "lop":[], "marko":["666", "created", "knows", "knows"]}] |
@GraphComputerVerificationStarGraphExceeded
Scenario: g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX
diff --git a/gremlin-test/features/sideEffect/Inject.feature b/gremlin-test/features/sideEffect/Inject.feature
index a186095..75edc15 100644
--- a/gremlin-test/features/sideEffect/Inject.feature
+++ b/gremlin-test/features/sideEffect/Inject.feature
@@ -51,13 +51,14 @@ Feature: Step - inject()
| p[v[marko],v[vadas],vadas,d[5].i] |
| p[v[marko],v[josh],josh,d[4].i] |
+ @GraphComputerVerificationInjectionNotSupported
Scenario: g_VX1X_injectXg_VX4XX_out_name
Given the modern graph
And using the parameter vid1 defined as "v[marko].id"
- And using the parameter v4 defined as "v[josh]"
+ And using the parameter v2 defined as "v[josh]"
And the traversal of
"""
- g.V(vid1).inject(v4).out().values("name")
+ g.V(vid1).inject(v2).out().values("name")
"""
When iterated to list
Then the result should be unordered
@@ -130,7 +131,6 @@ Feature: Step - inject()
| result |
| null |
-
Scenario: g_inject
Given the empty graph
And the traversal of
@@ -140,7 +140,6 @@ Feature: Step - inject()
When iterated to list
Then the result should be empty
- @GraphComputerVerificationInjectionNotSupported
Scenario: g_VX1X_valuesXageX_injectXnull_nullX
Given the modern graph
And using the parameter xx1 defined as "v[marko].id"
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index ea5eed3..d896228 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -125,7 +125,7 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.sid"), s -> g.V().has("name", s).id().next().toString()));
add(Pair.with(Pattern.compile("v\\[(.+)\\]"), s -> {
final Iterator<Object> itty = g.V().has("name", s).id();
- return String.format("new Vertex(\"%s\",\"%s\")", itty.hasNext() ? itty.next() : s, Vertex.DEFAULT_LABEL);
+ return String.format("new Vertex(%s,\"%s\")", itty.hasNext() ? itty.next() : s, Vertex.DEFAULT_LABEL);
}));
add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.id"), s -> getEdgeIdString(g, s)));
add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.sid"), s -> getEdgeIdString(g, s)));
@@ -138,9 +138,6 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("c\\[(.*)\\]"), s -> {
throw new AssumptionViolatedException("This test uses a lambda as a parameter which is not supported by gremlin-language");
}));
- add(Pair.with(Pattern.compile("v\\[(.+)\\]"), s -> {
- throw new AssumptionViolatedException("This test uses a Vertex as a parameter which is not supported by gremlin-language");
- }));
add(Pair.with(Pattern.compile("e\\[(.+)\\]"), s -> {
throw new AssumptionViolatedException("This test uses a Edge as a parameter which is not supported by gremlin-language");
}));
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/map/TinkerMergeVertexStep.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/map/TinkerMergeVertexStep.java
index 5876879..6771ebd 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/map/TinkerMergeVertexStep.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/map/TinkerMergeVertexStep.java
@@ -42,6 +42,7 @@ public class TinkerMergeVertexStep<S> extends MergeVertexStep<S> {
super(step.getTraversal(), step.isStart(), step.getSearchCreateTraversal());
if (step.getOnMatchTraversal() != null) this.addChildOption(Merge.onMatch, step.getOnMatchTraversal());
if (step.getOnCreateTraversal() != null) this.addChildOption(Merge.onCreate, step.getOnCreateTraversal());
+ if (step.getCallbackRegistry() != null) this.callbackRegistry = step.getCallbackRegistry();
}
@Override
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java
index 7d6f820..46856f8 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java
@@ -106,6 +106,7 @@ public class TinkerGraphWorld implements World {
private static final List<String> TAGS_TO_IGNORE = Arrays.asList(
"@StepDrop",
+ "@StepInject",
"@StepV",
"@GraphComputerVerificationOneBulk",
"@GraphComputerVerificationStrategyNotSupported",