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 2018/05/18 22:57:57 UTC

[1/2] tinkerpop git commit: TINKERPOP-1685 Added supportUpsert() feature

Repository: tinkerpop
Updated Branches:
  refs/heads/master d642c5d35 -> f98b57019


TINKERPOP-1685 Added supportUpsert() feature

Added to both VertexFeatures and EdgeFeatures. Gives graph providers a more explicit option for providing this type of capability.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/384718cd
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/384718cd
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/384718cd

Branch: refs/heads/master
Commit: 384718cdc93330cad8b2b78a3021220be3c9bebc
Parents: 31d2063
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Apr 11 07:02:43 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu May 10 09:16:19 2018 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 docs/src/upgrade/release-3.4.x.asciidoc         | 19 ++++++
 .../tinkerpop/gremlin/structure/Graph.java      | 31 ++++++++++
 .../tinkerpop/gremlin/structure/GraphTest.java  | 35 ++++++++++-
 .../tinkerpop/gremlin/structure/VertexTest.java | 62 ++++++++++++++++----
 5 files changed, 132 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/384718cd/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 0c350c8..b66df78 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 This release also includes changes from <<release-3-3-3, 3.3.3>>.
 
+* Added `supportsUpsert()` option to `VertexFeatures` and `EdgeFeatures`.
 * `min()` and `max()` now support all types implementing `Comparable`.
 * Change the `toString()` of `Path` to be standardized as other graph elements are.
 * `hadoop-gremlin` no longer generates a test artifact.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/384718cd/docs/src/upgrade/release-3.4.x.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index a3de9e7..3c881c3 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -230,3 +230,22 @@ long ago moved to the `Computer` infrastructure as methods for constructing a `T
 `TraversalEngine` were long ago removed.
 
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-1143[TINKERPOP-1143]
+
+==== Upsert Graph Feature
+
+Some `Graph` implementations may be able to offer upsert functionality for vertices and edges, which can help improve
+usability and performance. To help make it clear to users that a graph operates in this fashion, the `supportsUpsert()`
+feature has been added to both `Graph.VertexFeatures` and `Graph.EdgeFeatures`. By default, both of these methods will
+return `false`.
+
+Should a provider wish to support this feature, the behavior of `addV()` and/or `addE()` should change such that when
+a vertex or edge with the same identifier is provided, the respective step will insert the new element if that value
+is not present or update an existing element if it is found. The method by which the provider "identifies" an element
+is completely up to the capabilities of that provider. In the most simple fashion, a graph could simply check the
+value of the supplied `T.id`, however graphs that support some form of schema will likely have other methods for
+determining whether or not an existing element is present.
+
+The extent to which TinkerPop tests "upsert" is fairly narrow. Graph providers that choose to support this feature
+should consider their own test suites carefully to ensure appropriate coverage.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1685[TINKERPOP-1685]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/384718cd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java
index b142a9a..494ca8c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Graph.java
@@ -504,6 +504,7 @@ public interface Graph extends AutoCloseable, Host {
             public static final String FEATURE_DUPLICATE_MULTI_PROPERTIES = "DuplicateMultiProperties";
             public static final String FEATURE_META_PROPERTIES = "MetaProperties";
             public static final String FEATURE_REMOVE_VERTICES = "RemoveVertices";
+            public static final String FEATURE_UPSERT = "Upsert";
 
             /**
              * Gets the {@link VertexProperty.Cardinality} for a key.  By default, this method will return
@@ -565,6 +566,20 @@ public interface Graph extends AutoCloseable, Host {
             }
 
             /**
+             * Determines if the {@code Graph} implementation uses upsert functionality as opposed to insert
+             * functionality for {@link #addVertex(String)}. This feature gives graph providers some flexibility as
+             * to how graph mutations are treated. For graph providers, testing of this feature (as far as TinkerPop
+             * is concerned) only covers graphs that can support user supplied identifiers as there is no other way
+             * for TinkerPop to know what aspect of a vertex is unique to appropriately apply assertions. Graph
+             * providers, especially those who support schema features, may have other methods for uniquely identifying
+             * a vertex and should therefore resort to their own body of tests to validate this feature.
+             */
+            @FeatureDescriptor(name = FEATURE_UPSERT)
+            public default boolean supportsUpsert() {
+                return false;
+            }
+
+            /**
              * Gets features related to "properties" on a {@link Vertex}.
              */
             public default VertexPropertyFeatures properties() {
@@ -579,6 +594,7 @@ public interface Graph extends AutoCloseable, Host {
         public interface EdgeFeatures extends ElementFeatures {
             public static final String FEATURE_ADD_EDGES = "AddEdges";
             public static final String FEATURE_REMOVE_EDGES = "RemoveEdges";
+            public static final String FEATURE_UPSERT = "Upsert";
 
             /**
              * Determines if an {@link Edge} can be added to a {@code Vertex}.
@@ -597,6 +613,21 @@ public interface Graph extends AutoCloseable, Host {
             }
 
             /**
+             * Determines if the {@code Graph} implementation uses upsert functionality as opposed to insert
+             * functionality for {@link Vertex#addEdge(String, Vertex, Object...)}. This feature gives graph providers
+             * some flexibility as to how graph mutations are treated. For graph providers, testing of this feature
+             * (as far as TinkerPop is concerned) only covers graphs that can support user supplied identifiers as
+             * there is no other way for TinkerPop to know what aspect of a edge is unique to appropriately apply
+             * assertions. Graph providers, especially those who support schema features, may have other methods for
+             * uniquely identifying a edge and should therefore resort to their own body of tests to validate this
+             * feature.
+             */
+            @FeatureDescriptor(name = FEATURE_UPSERT)
+            public default boolean supportsUpsert() {
+                return false;
+            }
+
+            /**
              * Gets features related to "properties" on an {@link Edge}.
              */
             public default EdgePropertyFeatures properties() {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/384718cd/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphTest.java
index a667e6f..d8f0817 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/GraphTest.java
@@ -49,7 +49,12 @@ import java.util.stream.IntStream;
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.*;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -118,11 +123,12 @@ public class GraphTest extends AbstractGremlinTest {
     @Test
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_UPSERT, supported = false)
     public void shouldHaveExceptionConsistencyWhenAssigningSameIdOnVertex() {
         final Object o = graphProvider.convertId("1", Vertex.class);
-        graph.addVertex(T.id, o);
+        graph.addVertex(T.id, o, "name", "marko");
         try {
-            graph.addVertex(T.id, o);
+            graph.addVertex(T.id, o, "name", "stephen");
             fail("Assigning the same ID to an Element should throw an exception");
         } catch (Exception ex) {
             assertThat(ex, instanceOf(Graph.Exceptions.vertexWithIdAlreadyExists(0).getClass()));
@@ -132,6 +138,29 @@ public class GraphTest extends AbstractGremlinTest {
     @Test
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_UPSERT)
+    public void shouldUpsertWhenAssigningSameIdOnVertex() {
+        final Object o = graphProvider.convertId("1", Vertex.class);
+        graph.addVertex(T.id, o, "name", "marko");
+        tryCommit(graph, graph -> {
+            final Vertex v = graph.vertices(o).next();
+            assertEquals(o, v.id());
+            assertEquals("marko", v.value("name"));
+            assertVertexEdgeCounts(graph, 1, 0);
+        });
+
+        graph.addVertex(T.id, o, "name", "stephen");
+        tryCommit(graph, graph -> {
+            final Vertex v = graph.vertices(o).next();
+            assertEquals(o, v.id());
+            assertEquals("stephen", v.value("name"));
+            assertVertexEdgeCounts(graph, 1, 0);
+        });
+    }
+
+    @Test
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
+    @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NUMERIC_IDS)
     public void shouldAddVertexWithUserSuppliedNumericId() {
         graph.addVertex(T.id, 1000l);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/384718cd/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexTest.java
index 8062fd1..6108456 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexTest.java
@@ -37,9 +37,20 @@ import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
-import static org.apache.tinkerpop.gremlin.structure.Graph.Features.PropertyFeatures.*;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.DataTypeFeatures.FEATURE_BOOLEAN_VALUES;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.DataTypeFeatures.FEATURE_DOUBLE_VALUES;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.DataTypeFeatures.FEATURE_FLOAT_VALUES;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.DataTypeFeatures.FEATURE_INTEGER_VALUES;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.DataTypeFeatures.FEATURE_LONG_VALUES;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.DataTypeFeatures.FEATURE_STRING_VALUES;
 import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -56,10 +67,10 @@ public class VertexTest {
         @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_NUMERIC_IDS)
         public void shouldAddEdgeWithUserSuppliedNumericId() {
             final Vertex v = graph.addVertex();
-            v.addEdge("self", v, T.id, 1000l);
+            v.addEdge("self", v, T.id, 1000L);
             tryCommit(graph, graph -> {
-                final Edge e = graph.edges(1000l).next();
-                assertEquals(1000l, e.id());
+                final Edge e = graph.edges(1000L).next();
+                assertEquals(1000L, e.id());
             });
         }
 
@@ -251,18 +262,43 @@ public class VertexTest {
         @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
         @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_USER_SUPPLIED_IDS)
+        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_UPSERT, supported = false)
         public void shouldHaveExceptionConsistencyWhenAssigningSameIdOnEdge() {
             final Vertex v = graph.addVertex();
             final Object o = graphProvider.convertId("1", Edge.class);
-            v.addEdge("self", v, T.id, o);
+            v.addEdge("self", v, T.id, o, "weight", 1);
 
             try {
-                v.addEdge("self", v, T.id, o);
+                v.addEdge("self", v, T.id, o, "weight", 1);
                 fail("Assigning the same ID to an Element should throw an exception");
             } catch (Exception ex) {
                 validateException(Graph.Exceptions.edgeWithIdAlreadyExists(o), ex);
             }
+        }
 
+        @Test
+        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
+        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_USER_SUPPLIED_IDS)
+        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_UPSERT)
+        public void shouldUpsertWhenAssigningSameIdOnEdge() {
+            final Vertex v = graph.addVertex();
+            final Object o = graphProvider.convertId("1", Edge.class);
+            v.addEdge("self", v, T.id, o, "weight", 1);
+            tryCommit(graph, graph -> {
+                final Edge e = graph.edges(o).next();
+                assertEquals(o, e.id());
+                assertEquals(1, (int) e.value("weight"));
+                assertVertexEdgeCounts(graph, 1, 1);
+            });
+
+            v.addEdge("self", v, T.id, o, "weight", 2);
+            tryCommit(graph, graph -> {
+                final Edge e = graph.edges(o).next();
+                assertEquals(o, e.id());
+                assertEquals(2, (int) e.value("weight"));
+                assertVertexEdgeCounts(graph, 1, 1);
+            });
         }
 
         @Test
@@ -289,8 +325,8 @@ public class VertexTest {
         @Test
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
-        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_STRING_VALUES)
-        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_INTEGER_VALUES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES)
         public void shouldHaveStandardStringRepresentationWithProperties() {
             final Vertex v = graph.addVertex("name", "marko", "age", 34);
             assertEquals(StringFactory.vertexString(v), v.toString());
@@ -462,9 +498,9 @@ public class VertexTest {
         @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_LONG_VALUES)
         public void shouldAutotypeLongProperties() {
             final Vertex v = graph.addVertex();
-            v.property(VertexProperty.Cardinality.single, "long", 1l);
+            v.property(VertexProperty.Cardinality.single, "long", 1L);
             final Long best = v.value("long");
-            assertEquals(best, Long.valueOf(1l));
+            assertEquals(best, Long.valueOf(1L));
         }
 
         @Test
@@ -516,9 +552,9 @@ public class VertexTest {
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
         @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
-        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_INTEGER_VALUES)
+        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES)
         @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_PROPERTY)
-        @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = Graph.Features.EdgePropertyFeatures.FEATURE_INTEGER_VALUES)
+        @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = FEATURE_INTEGER_VALUES)
         @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_REMOVE_VERTICES)
         public void shouldNotGetConcurrentModificationException() {
             for (int i = 0; i < 25; i++) {


[2/2] tinkerpop git commit: Merge branch 'TINKERPOP-1685'

Posted by sp...@apache.org.
Merge branch 'TINKERPOP-1685'


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/f98b5701
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/f98b5701
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/f98b5701

Branch: refs/heads/master
Commit: f98b5701949a7682cfa5fa83942d4fa41a2d2fae
Parents: d642c5d 384718c
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri May 18 18:57:41 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri May 18 18:57:41 2018 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 docs/src/upgrade/release-3.4.x.asciidoc         | 19 ++++++
 .../tinkerpop/gremlin/structure/Graph.java      | 31 ++++++++++
 .../tinkerpop/gremlin/structure/GraphTest.java  | 35 ++++++++++-
 .../tinkerpop/gremlin/structure/VertexTest.java | 62 ++++++++++++++++----
 5 files changed, 132 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f98b5701/CHANGELOG.asciidoc
----------------------------------------------------------------------