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 2021/11/09 12:13:50 UTC

[tinkerpop] branch TINKERPOP-2613 updated (1d2a845 -> 9ff183f)

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

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


 discard 1d2a845  TINKERPOP-2613 Improved behavior of V(null)
     new 9ff183f  TINKERPOP-2613 Improved behavior of V(null)

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (1d2a845)
            \
             N -- N -- N   refs/heads/TINKERPOP-2613 (9ff183f)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

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


Summary of changes:
 CHANGELOG.asciidoc                                 |  2 +-
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  3 +++
 .../gremlin-javascript/test/cucumber/gremlin.js    |  4 ++-
 gremlin-python/src/main/python/radish/gremlin.py   |  3 +++
 gremlin-test/features/map/Vertex.feature           | 31 ++++++++++++++++++++++
 .../gremlin/neo4j/structure/Neo4jGraph.java        | 16 ++++++++---
 6 files changed, 53 insertions(+), 6 deletions(-)

[tinkerpop] 01/01: TINKERPOP-2613 Improved behavior of V(null)

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

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

commit 9ff183f1876be7baa886cd93e5f5b635bcb7a266
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Tue Nov 9 06:27:40 2021 -0500

    TINKERPOP-2613 Improved behavior of V(null)
    
    Prevented NPE and instead filtered results.
---
 CHANGELOG.asciidoc                                 |  1 +
 .../traversal/dsl/graph/GraphTraversal.java        |  9 ++-
 .../traversal/dsl/graph/GraphTraversalSource.java  | 14 ++--
 .../gremlin/structure/util/ElementHelper.java      |  4 +-
 .../translator/JavascriptTranslatorTest.java       |  8 +-
 .../Process/Traversal/GraphTraversal.cs            | 11 ++-
 .../Process/Traversal/GraphTraversalSource.cs      | 22 +++++-
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  8 ++
 gremlin-javascript/build/generate.groovy           |  4 +
 .../gremlin-javascript/test/cucumber/gremlin.js    |  7 ++
 gremlin-python/src/main/python/radish/gremlin.py   |  8 ++
 gremlin-test/features/map/Vertex.feature           | 85 ++++++++++++++++++++++
 .../gremlin/neo4j/structure/Neo4jGraph.java        | 16 +++-
 .../gremlin/tinkergraph/structure/TinkerGraph.java |  2 +
 14 files changed, 177 insertions(+), 22 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d3fc76a..7e96d38 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -30,6 +30,7 @@ limitations under the License.
 * Created `gremlin-annotations` module where the `@GremlinDsl` annotation and related code has been moved.
 * Removed `groovy` and `groovy-json` dependencies from `gremlin-driver` as well as related `JsonBuilder` serialization support.
 * Replaced log4j usage with logback where builds rely on and packaged distributions now contain the latter.
+* Improved behavior of `V()` and `E()` when `null` is an argument producing a filtering behavior rather than an exception.
 * Prevented metrics computation unless the traversal is in a locked state.
 * Created a way to produce a corpus of Gremlin traversals via `FeatureReader` and `DocumentationReader` in `gremlin-language`.
 * Exposed Gherkin tests as part of the provider test suite.
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 9a45300..cd64f55 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
@@ -315,8 +315,10 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      * @since 3.1.0-incubating
      */
     public default GraphTraversal<S, Vertex> V(final Object... vertexIdsOrElements) {
-        this.asAdmin().getBytecode().addStep(Symbols.V, vertexIdsOrElements);
-        return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), Vertex.class, false, vertexIdsOrElements));
+        // a single null is [null]
+        final Object[] ids = null == vertexIdsOrElements ? new Object[] { null } : vertexIdsOrElements;
+        this.asAdmin().getBytecode().addStep(Symbols.V, ids);
+        return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), Vertex.class, false, ids));
     }
 
     /**
@@ -1606,8 +1608,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     public default GraphTraversal<S, E> hasId(final Object id, final Object... otherIds) {
         if (id instanceof P) {
             return this.hasId((P) id);
-        }
-        else {
+        } else {
             Object[] ids;
             if (id instanceof Object[]) {
                 ids = (Object[]) id;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index b7471b1..cae7e5c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -365,21 +365,25 @@ public class GraphTraversalSource implements TraversalSource {
      * unique identifier.
      */
     public GraphTraversal<Vertex, Vertex> V(final Object... vertexIds) {
+        // a single null is [null]
+        final Object[] ids = null == vertexIds ? new Object[] { null } : vertexIds;
         final GraphTraversalSource clone = this.clone();
-        clone.bytecode.addStep(GraphTraversal.Symbols.V, vertexIds);
+        clone.bytecode.addStep(GraphTraversal.Symbols.V, ids);
         final GraphTraversal.Admin<Vertex, Vertex> traversal = new DefaultGraphTraversal<>(clone);
-        return traversal.addStep(new GraphStep<>(traversal, Vertex.class, true, vertexIds));
+        return traversal.addStep(new GraphStep<>(traversal, Vertex.class, true, ids));
     }
 
     /**
      * Spawns a {@link GraphTraversal} starting with all edges or some subset of edges as specified by their unique
      * identifier.
      */
-    public GraphTraversal<Edge, Edge> E(final Object... edgesIds) {
+    public GraphTraversal<Edge, Edge> E(final Object... edgeIds) {
+        // a single null is [null]
+        final Object[] ids = null == edgeIds ? new Object[] { null } : edgeIds;
         final GraphTraversalSource clone = this.clone();
-        clone.bytecode.addStep(GraphTraversal.Symbols.E, edgesIds);
+        clone.bytecode.addStep(GraphTraversal.Symbols.E, ids);
         final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone);
-        return traversal.addStep(new GraphStep<>(traversal, Edge.class, true, edgesIds));
+        return traversal.addStep(new GraphStep<>(traversal, Edge.class, true, ids));
     }
 
     /**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
index 48e8733..a742e7b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
@@ -549,10 +549,10 @@ public final class ElementHelper {
         // it is OK to evaluate equality of ids via toString() now given that the toString() the test suite
         // enforces the value of id.()toString() to be a first class representation of the identifier
         if (1 == providedIds.length) {
-            return id.toString().equals(providedIds[0].toString());
+            return id != null && providedIds[0] != null && id.toString().equals(providedIds[0].toString());
         } else {
             for (final Object temp : providedIds) {
-                if (temp.toString().equals(id.toString()))
+                if (id != null && temp != null && temp.toString().equals(id.toString()))
                     return true;
             }
             return false;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/JavascriptTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/JavascriptTranslatorTest.java
index 1a0f1c0..f2db89b 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/JavascriptTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/JavascriptTranslatorTest.java
@@ -119,7 +119,13 @@ public class JavascriptTranslatorTest {
 
     @Test
     public void shouldHaveNull() {
-        translator.translate(g.inject(null, null).asAdmin().getBytecode()).getScript();
+        assertEquals("g.inject(null,null)", translator.translate(g.inject(null, null).asAdmin().getBytecode()).getScript());
+        assertEquals("g.V()", translator.translate(g.V().asAdmin().getBytecode()).getScript());
+        assertEquals("g.V(null)", translator.translate(g.V(null).asAdmin().getBytecode()).getScript());
+        assertEquals("g.V(null,null)", translator.translate(g.V(null, null).asAdmin().getBytecode()).getScript());
+        assertEquals("g.E()", translator.translate(g.E().asAdmin().getBytecode()).getScript());
+        assertEquals("g.E(null)", translator.translate(g.E(null).asAdmin().getBytecode()).getScript());
+        assertEquals("g.E(null,null)", translator.translate(g.E(null, null).asAdmin().getBytecode()).getScript());
     }
 
     @Test
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 2bc4de8..328e506 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -79,8 +79,15 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         public GraphTraversal<S, Vertex> V (params object[] vertexIdsOrElements)
         {
-            var args = new List<object>(0 + vertexIdsOrElements.Length) {};
-            args.AddRange(vertexIdsOrElements);
+            var args = null == vertexIdsOrElements ? new List<object>(1) {} : new List<object>(0 + vertexIdsOrElements.Length) {};
+            if (null == vertexIdsOrElements)
+            {
+                args.Add(null);
+            }
+            else
+            {
+                args.AddRange(vertexIdsOrElements);
+            }
             Bytecode.AddStep("V", args.ToArray());
             return Wrap<S, Vertex>(this);
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index 2ab9d01..ae5b1d9 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -296,8 +296,15 @@ namespace Gremlin.Net.Process.Traversal
         public GraphTraversal<Edge, Edge> E(params object[] edgesIds)
         {
             var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
-            var args = new List<object>(0 + edgesIds.Length) {};
-            args.AddRange(edgesIds);
+            var args = null == edgesIds ? new List<object>(1) {} : new List<object>(0 + edgesIds.Length) {};
+            if (null == edgesIds)
+            {
+                args.Add(null);
+            }
+            else
+            {
+                args.AddRange(edgesIds);
+            }
             traversal.Bytecode.AddStep("E", args.ToArray());
             return traversal;
         }
@@ -309,8 +316,15 @@ namespace Gremlin.Net.Process.Traversal
         public GraphTraversal<Vertex, Vertex> V(params object[] vertexIds)
         {
             var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
-            var args = new List<object>(0 + vertexIds.Length) {};
-            args.AddRange(vertexIds);
+            var args = null == vertexIds ? new List<object>(1) {} : new List<object>(0 + vertexIds.Length) {};
+            if (null == vertexIds)
+            {
+                args.Add(null);
+            }
+            else
+            {
+                args.AddRange(vertexIds);
+            }
             traversal.Bytecode.AddStep("V", args.ToArray());
             return traversal;
         }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 2c8d242..76a4b6a 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -646,6 +646,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).ValueMap<object,object>().With("~tinkerpop.valueMap.tokens")}}, 
                {"g_VX1X_valueMapXname_locationX_byXunfoldX_by", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ValueMap<object,object>("name","location").By(__.Unfold<object>()).By()}}, 
                {"g_V_valueMapXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>("name","age",null)}}, 
+               {"g_VXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(null)}}, 
+               {"g_VXlistXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"])}}, 
+               {"g_VX1_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"],null)}}, 
                {"g_VXlistX1_2_3XX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"]).Values<object>("name")}}, 
                {"g_VXlistXv1_v2_v3XX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"]).Values<object>("name")}}, 
                {"g_V", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V()}}, 
@@ -659,6 +662,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_EXe11X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["e11"])}}, 
                {"g_EXe7_e11X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["e7"],p["e11"])}}, 
                {"g_EXlistXe7_e11XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["xx1"])}}, 
+               {"g_EXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(null)}}, 
+               {"g_EXlistXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["xx1"])}}, 
+               {"g_EX11_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"],null)}}, 
                {"g_VX1X_outE", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE()}}, 
                {"g_VX2X_outE", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid2"]).InE()}}, 
                {"g_VX4X_bothEXcreatedX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid4"]).BothE("created")}}, 
@@ -686,6 +692,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").V().HasLabel("software").Values<object>("name")}}, 
                {"g_V_hasLabelXloopsX_bothEXselfX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("loops").BothE("self")}}, 
                {"g_V_hasLabelXloopsX_bothXselfX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("loops").Both("self")}}, 
+               {"g_injectX1X_VXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(1).V(null)}}, 
+               {"g_injectX1X_VX1_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(1).V(p["vid1"],null)}}, 
                {"Primitives_Number_eqXintX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}}, 
                {"g_V_valueXnameX_aggregateXxX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Aggregate("x").Cap<object>("x")}}, 
                {"g_V_valueXnameX_aggregateXglobal_xX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Aggregate(Scope.Global,"x").Cap<object>("x")}}, 
diff --git a/gremlin-javascript/build/generate.groovy b/gremlin-javascript/build/generate.groovy
index 75e7087..572d29c 100644
--- a/gremlin-javascript/build/generate.groovy
+++ b/gremlin-javascript/build/generate.groovy
@@ -99,6 +99,10 @@ radishGremlinFile.withWriter('UTF-8') { Writer writer ->
     // solution may become necessary as testing of nulls expands.
     def staticTranslate = [
             g_injectXnull_nullX: "    g_injectXnull_nullX: [function({g}) { return g.inject(null,null) }], ",
+            g_V_hasIdXnullX: "    g_V_hasIdXnullX: [function({g}) { return g.V().hasId(null) }], ",
+            g_V_hasIdX1_nullX: "    g_V_hasIdX1_nullX: [function({g, vid1}) { return g.V().hasId(vid1,null) }], ",
+            g_injectX1X_VXnullX: "    g_injectX1X_VXnullX: [function({g}) { return g.inject(1).V(null) }], ",
+            g_injectX1X_VX1_nullX: "    g_injectX1X_VX1_nullX: [function({g, vid1}) { return g.inject(1).V(vid1,null) }], ",
             g_VX1X_valuesXageX_injectXnull_nullX: "    g_VX1X_valuesXageX_injectXnull_nullX: [function({g, xx1}) { return g.V(xx1).values(\"age\").inject(null,null) }], "
     ]
 
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 8507405..538b630 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
@@ -635,6 +635,9 @@ const gremlins = {
     g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX: [function({g}) { return g.V().hasLabel("person").filter(__.outE("created")).valueMap().with_("~tinkerpop.valueMap.tokens") }], 
     g_VX1X_valueMapXname_locationX_byXunfoldX_by: [function({g, vid1}) { return g.V(vid1).valueMap("name","location").by(__.unfold()).by() }], 
     g_V_valueMapXname_age_nullX: [function({g}) { return g.V().valueMap("name","age",null) }], 
+    g_VXnullX: [function({g}) { return g.V(null) }], 
+    g_VXlistXnullXX: [function({g, xx1}) { return g.V(xx1) }, function({g, xx1}) { return g.E(xx1) }], 
+    g_VX1_nullX: [function({g, vid1}) { return g.V(vid1,null) }], 
     g_VXlistX1_2_3XX_name: [function({g, xx1}) { return g.V(xx1).values("name") }], 
     g_VXlistXv1_v2_v3XX_name: [function({g, xx1}) { return g.V(xx1).values("name") }], 
     g_V: [function({g}) { return g.V() }], 
@@ -648,6 +651,8 @@ const gremlins = {
     g_EXe11X: [function({g, e11}) { return g.E(e11) }], 
     g_EXe7_e11X: [function({g, e7, e11}) { return g.E(e7,e11) }], 
     g_EXlistXe7_e11XX: [function({g, xx1}) { return g.E(xx1) }], 
+    g_EXnullX: [function({g}) { return g.E(null) }], 
+    g_EX11_nullX: [function({g, eid11}) { return g.E(eid11,null) }], 
     g_VX1X_outE: [function({g, vid1}) { return g.V(vid1).outE() }], 
     g_VX2X_outE: [function({g, vid2}) { return g.V(vid2).inE() }], 
     g_VX4X_bothEXcreatedX: [function({g, vid4}) { return g.V(vid4).bothE("created") }], 
@@ -675,6 +680,8 @@ const gremlins = {
     g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name: [function({g}) { return g.V().hasLabel("person").V().hasLabel("software").values("name") }], 
     g_V_hasLabelXloopsX_bothEXselfX: [function({g}) { return g.V().hasLabel("loops").bothE("self") }], 
     g_V_hasLabelXloopsX_bothXselfX: [function({g}) { return g.V().hasLabel("loops").both("self") }], 
+    g_injectX1X_VXnullX: [function({g}) { return g.inject(1).V(null) }], 
+    g_injectX1X_VX1_nullX: [function({g, vid1}) { return g.inject(1).V(vid1,null) }], 
     Primitives_Number_eqXintX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }], 
     g_V_valueXnameX_aggregateXxX_capXxX: [function({g}) { return g.V().values("name").aggregate("x").cap("x") }], 
     g_V_valueXnameX_aggregateXglobal_xX_capXxX: [function({g}) { return g.V().values("name").aggregate(Scope.global,"x").cap("x") }], 
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 5f9535a..b99100b 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -620,6 +620,9 @@ world.gremlins = {
     'g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX': [(lambda g:g.V().hasLabel('person').filter(__.outE('created')).valueMap().with_('~tinkerpop.valueMap.tokens'))], 
     'g_VX1X_valueMapXname_locationX_byXunfoldX_by': [(lambda g, vid1=None:g.V(vid1).valueMap('name','location').by(__.unfold()).by())], 
     'g_V_valueMapXname_age_nullX': [(lambda g:g.V().valueMap('name','age',None))], 
+    'g_VXnullX': [(lambda g:g.V(None))], 
+    'g_VXlistXnullXX': [(lambda g, xx1=None:g.V(xx1))], 
+    'g_VX1_nullX': [(lambda g, vid1=None:g.V(vid1,None))], 
     'g_VXlistX1_2_3XX_name': [(lambda g, xx1=None:g.V(xx1).name)], 
     'g_VXlistXv1_v2_v3XX_name': [(lambda g, xx1=None:g.V(xx1).name)], 
     'g_V': [(lambda g:g.V())], 
@@ -633,6 +636,9 @@ world.gremlins = {
     'g_EXe11X': [(lambda g, e11=None:g.E(e11))], 
     'g_EXe7_e11X': [(lambda g, e7=None,e11=None:g.E(e7,e11))], 
     'g_EXlistXe7_e11XX': [(lambda g, xx1=None:g.E(xx1))], 
+    'g_EXnullX': [(lambda g:g.E(None))], 
+    'g_EXlistXnullXX': [(lambda g, xx1=None:g.E(xx1))], 
+    'g_EX11_nullX': [(lambda g, eid11=None:g.E(eid11,None))], 
     'g_VX1X_outE': [(lambda g, vid1=None:g.V(vid1).outE())], 
     'g_VX2X_outE': [(lambda g, vid2=None:g.V(vid2).inE())], 
     'g_VX4X_bothEXcreatedX': [(lambda g, vid4=None:g.V(vid4).bothE('created'))], 
@@ -660,6 +666,8 @@ world.gremlins = {
     'g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name': [(lambda g:g.V().hasLabel('person').V().hasLabel('software').name)], 
     'g_V_hasLabelXloopsX_bothEXselfX': [(lambda g:g.V().hasLabel('loops').bothE('self'))], 
     'g_V_hasLabelXloopsX_bothXselfX': [(lambda g:g.V().hasLabel('loops').both('self'))], 
+    'g_injectX1X_VXnullX': [(lambda g:g.inject(1).V(None))], 
+    'g_injectX1X_VX1_nullX': [(lambda g, vid1=None:g.inject(1).V(vid1,None))], 
     'Primitives_Number_eqXintX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))], 
     'g_V_valueXnameX_aggregateXxX_capXxX': [(lambda g:g.V().name.aggregate('x').cap('x'))], 
     'g_V_valueXnameX_aggregateXglobal_xX_capXxX': [(lambda g:g.V().name.aggregate(Scope.global_,'x').cap('x'))], 
diff --git a/gremlin-test/features/map/Vertex.feature b/gremlin-test/features/map/Vertex.feature
index 37738bb..f0b3c95 100644
--- a/gremlin-test/features/map/Vertex.feature
+++ b/gremlin-test/features/map/Vertex.feature
@@ -18,6 +18,37 @@
 @StepClassMap @StepVertex
 Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
 
+  Scenario: g_VXnullX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V(null)
+      """
+    When iterated to list
+    Then the result should be empty
+
+  Scenario: g_VXlistXnullXX
+    Given the modern graph
+    And using the parameter xx1 defined as "l[null]"
+    And the traversal of
+      """
+      g.V(xx1)
+      """
+    When iterated to list
+    Then the result should be empty
+
+  Scenario: g_VX1_nullX
+    Given the modern graph
+    And using the parameter vid1 defined as "v[marko].id"
+    And the traversal of
+      """
+      g.V(vid1,null)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[marko] |
+
   Scenario: g_VXlistX1_2_3XX_name
     Given the modern graph
     And using the parameter xx1 defined as "l[v[marko].id,v[vadas].id,v[lop].id]"
@@ -195,6 +226,37 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
       | e[marko-knows->vadas] |
       | e[josh-created->lop] |
 
+  Scenario: g_EXnullX
+    Given the modern graph
+    And the traversal of
+      """
+      g.E(null)
+      """
+    When iterated to list
+    Then the result should be empty
+
+  Scenario: g_EXlistXnullXX
+    Given the modern graph
+    And using the parameter xx1 defined as "l[null]"
+    And the traversal of
+      """
+      g.E(xx1)
+      """
+    When iterated to list
+    Then the result should be empty
+
+  Scenario: g_EX11_nullX
+    Given the modern graph
+    And using the parameter eid11 defined as "e[josh-created->lop].id"
+    And the traversal of
+      """
+      g.E(eid11,null)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | e[josh-created->lop] |
+
   Scenario: g_VX1X_outE
     Given the modern graph
     And using the parameter vid1 defined as "v[marko].id"
@@ -579,3 +641,26 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
       | result |
       | v[loop] |
       | v[loop] |
+
+  @GraphComputerVerificationInjectionNotSupported @GraphComputerVerificationMidVNotSupported
+  Scenario: g_injectX1X_VXnullX
+    Given the modern graph
+    And the traversal of
+      """
+      g.inject(1).V(null)
+      """
+    When iterated to list
+    Then the result should be empty
+
+  @GraphComputerVerificationInjectionNotSupported @GraphComputerVerificationMidVNotSupported
+  Scenario: g_injectX1X_VX1_nullX
+    Given the modern graph
+    And using the parameter vid1 defined as "v[marko].id"
+    And the traversal of
+      """
+      g.inject(1).V(vid1,null)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[marko] |
\ No newline at end of file
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
index df63c97..b23c558 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
@@ -150,12 +150,16 @@ public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
                             return ((Number) id).longValue();
                         else if (id instanceof String)
                             return Long.valueOf(id.toString());
-                        else if (id instanceof Vertex) {
+                        else if (id instanceof Vertex)
                             return (Long) ((Vertex) id).id();
-                        } else
+                        else if (null == id)
+                            return null;
+                        else
                             throw new IllegalArgumentException("Unknown vertex id type: " + id);
                     })
                     .flatMap(id -> {
+                        // can't have a null id so just filter
+                        if (null == id) return Stream.empty();
                         try {
                             return Stream.of(this.baseGraph.getNodeById(id));
                         } catch (final RuntimeException e) {
@@ -180,12 +184,16 @@ public final class Neo4jGraph implements Graph, WrappedGraph<Neo4jGraphAPI> {
                             return ((Number) id).longValue();
                         else if (id instanceof String)
                             return Long.valueOf(id.toString());
-                        else if (id instanceof Edge) {
+                        else if (id instanceof Edge)
                             return (Long) ((Edge) id).id();
-                        } else
+                        else if (null == id)
+                            return null;
+                        else
                             throw new IllegalArgumentException("Unknown edge id type: " + id);
                     })
                     .flatMap(id -> {
+                        // can't have a null id so just filter
+                        if (null == id) return Stream.empty();
                         try {
                             return Stream.of(this.baseGraph.getRelationshipById(id));
                         } catch (final RuntimeException e) {
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
index 0343302..b9dda16 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
@@ -316,6 +316,8 @@ public final class TinkerGraph implements Graph {
             // the assumption is that if it's already an Element, its identifier must be valid to the Graph and to
             // its associated IdManager. All other objects are passed to the IdManager for conversion.
             return new TinkerGraphIterator<>(IteratorUtils.filter(IteratorUtils.map(idList, id -> {
+                // ids cant be null so all of those filter out
+                if (null == id) return null;
                 final Object iid = clazz.isAssignableFrom(id.getClass()) ? clazz.cast(id).id() : idManager.convert(id);
                 return elements.get(idManager.convert(iid));
             }).iterator(), Objects::nonNull));