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 2023/04/20 21:48:37 UTC
[tinkerpop] 01/01: TINKERPOP-2928 Fixed bug in element() with edge properties CTR
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2928
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit c380f759e274143cf895888f45743906a933d19c
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Thu Apr 20 14:57:02 2023 -0400
TINKERPOP-2928 Fixed bug in element() with edge properties CTR
---
CHANGELOG.asciidoc | 1 +
docs/src/reference/the-traversal.asciidoc | 2 +-
.../process/traversal/step/map/ElementStep.java | 2 +-
.../strategy/optimization/LazyBarrierStrategy.java | 7 +-
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 10 ++-
gremlin-go/driver/cucumber/gremlin.go | 10 ++-
.../gremlin-javascript/test/cucumber/gremlin.js | 10 ++-
gremlin-python/src/main/python/radish/gremlin.py | 10 ++-
.../gremlin/test/features/map/Element.feature | 81 ++++++++++++++++++++--
9 files changed, 110 insertions(+), 23 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 49df090a76..31e8cec8e7 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-5-6, 3.5.6>>.
+* Fixed bug in `element()` when traversing from edges where bulking was enabled.
* Refactored `PropertyMapStep` to improve extensibility by providers.
* Fixed bug in grammar that prevented declaration of a `Map` key named `new` without quotes.
* Fixed bug in grammar that prevented parsing of `Map` key surrounded by parenthesis which is allowable in Groovy.
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 1450c944ca..b094418e94 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -1258,7 +1258,7 @@ link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre
The `element()` step is a no-argument step that traverses from a `Property` to the `Element` that owns it.
-[gremlin-groovy]
+[gremlin-groovy,theCrew]
----
g.V().properties().element() <1>
g.E().properties().element() <2>
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementStep.java
index 092289c7a3..62b2bf33c2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementStep.java
@@ -28,7 +28,7 @@ import java.util.Collections;
import java.util.Set;
/**
- * Traverse from a Property to its Element.
+ * Traverse from a {@link Property} to its {@link Element}.
*
* @author Mike Personick (http://github.com/mikepersonick)
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
index d7cf224baa..adb7b40460 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
@@ -26,13 +26,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DropStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ElementStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FlatMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ProfileSideEffectStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
@@ -78,12 +78,13 @@ public final class LazyBarrierStrategy extends AbstractTraversalStrategy<Travers
@Override
public void apply(final Traversal.Admin<?, ?> traversal) {
- // drop() is a problem for bulked edge/meta properties because of Property equality changes in TINKERPOP-2318
+ // drop()/element() is a problem for bulked edge/meta properties because of Property equality changes in TINKERPOP-2318
// which made it so that a Property is equal if the key/value is equal. as a result, they bulk together which
// is fine for almost all cases except when you wish to drop the property.
if (TraversalHelper.onGraphComputer(traversal) ||
traversal.getTraverserRequirements().contains(TraverserRequirement.PATH) ||
- TraversalHelper.hasStepOfAssignableClass(DropStep.class, traversal))
+ TraversalHelper.hasStepOfAssignableClass(DropStep.class, traversal)||
+ TraversalHelper.hasStepOfAssignableClass(ElementStep.class, traversal))
return;
boolean foundFlatMap = false;
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 7feb9ade10..1e2a08eabc 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -497,9 +497,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_E_sampleX1X_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Sample(1).Count()}},
{"g_V_sampleX1X_byXageX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Sample(1).By("age").Count()}},
{"g_V_order_byXnoX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By("no").Count()}},
- {"g_V_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"]).Properties<object>().Element().Limit<object>(1)}},
- {"g_E_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["xx1"]).Properties<object>().Element().Limit<object>(1)}},
- {"g_V_properties_properties_element_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"]).Properties<object>().Properties<object>().Element().Element().Limit<object>(1)}},
+ {"g_VX1X_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v2"]).Properties<object>().Element().Limit<object>(1)}},
+ {"g_V_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>().Element()}},
+ {"g_V_propertiesXageX_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>("age").Element()}},
+ {"g_EX_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).Properties<object>().Element().Limit<object>(1)}},
+ {"g_E_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Properties<object>().Element()}},
+ {"g_VXv7_properties_properties_element_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v7"]).Properties<object>().Properties<object>().Element().Element().Limit<object>(1)}},
+ {"g_V_properties_properties_element_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v7"]).Properties<object>().Properties<object>().Element().Element()}},
{"g_V_elementMap", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ElementMap<object>()}},
{"g_V_elementMapXname_ageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ElementMap<object>("name","age")}},
{"g_EX11X_elementMap", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).ElementMap<object>()}},
diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index 036d4b50a2..63f255b3fd 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -468,9 +468,13 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_E_sampleX1X_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Sample(1).Count()}},
"g_V_sampleX1X_byXageX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Sample(1).By("age").Count()}},
"g_V_order_byXnoX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Order().By("no").Count()}},
- "g_V_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["xx1"]).Properties().Element().Limit(1)}},
- "g_E_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["xx1"]).Properties().Element().Limit(1)}},
- "g_V_properties_properties_element_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["xx1"]).Properties().Properties().Element().Element().Limit(1)}},
+ "g_VX1X_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["v2"]).Properties().Element().Limit(1)}},
+ "g_V_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties().Element()}},
+ "g_V_propertiesXageX_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("age").Element()}},
+ "g_EX_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"]).Properties().Element().Limit(1)}},
+ "g_E_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties().Element()}},
+ "g_VXv7_properties_properties_element_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["v7"]).Properties().Properties().Element().Element().Limit(1)}},
+ "g_V_properties_properties_element_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["v7"]).Properties().Properties().Element().Element()}},
"g_V_elementMap": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().ElementMap()}},
"g_V_elementMapXname_ageX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().ElementMap("name", "age")}},
"g_EX11X_elementMap": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"]).ElementMap()}},
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 93d0ad4e55..e01cd30e54 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
@@ -487,9 +487,13 @@ const gremlins = {
g_E_sampleX1X_count: [function({g}) { return g.E().sample(1).count() }],
g_V_sampleX1X_byXageX_count: [function({g}) { return g.V().sample(1).by("age").count() }],
g_V_order_byXnoX_count: [function({g}) { return g.V().order().by("no").count() }],
- g_V_properties_element: [function({g, xx1}) { return g.V(xx1).properties().element().limit(1) }],
- g_E_properties_element: [function({g, xx1}) { return g.E(xx1).properties().element().limit(1) }],
- g_V_properties_properties_element_element: [function({g, xx1}) { return g.V(xx1).properties().properties().element().element().limit(1) }],
+ g_VX1X_properties_element: [function({g, v2}) { return g.V(v2).properties().element().limit(1) }],
+ g_V_properties_element: [function({g}) { return g.V().properties().element() }],
+ g_V_propertiesXageX_element: [function({g}) { return g.V().properties("age").element() }],
+ g_EX_properties_element: [function({g, eid11}) { return g.E(eid11).properties().element().limit(1) }],
+ g_E_properties_element: [function({g}) { return g.E().properties().element() }],
+ g_VXv7_properties_properties_element_element: [function({g, v7}) { return g.V(v7).properties().properties().element().element().limit(1) }],
+ g_V_properties_properties_element_element: [function({g, v7}) { return g.V(v7).properties().properties().element().element() }],
g_V_elementMap: [function({g}) { return g.V().elementMap() }],
g_V_elementMapXname_ageX: [function({g}) { return g.V().elementMap("name","age") }],
g_EX11X_elementMap: [function({g, eid11}) { return g.E(eid11).elementMap() }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 9b0deb0710..6aeddf7f47 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -469,9 +469,13 @@ world.gremlins = {
'g_E_sampleX1X_count': [(lambda g:g.E().sample(1).count())],
'g_V_sampleX1X_byXageX_count': [(lambda g:g.V().sample(1).by('age').count())],
'g_V_order_byXnoX_count': [(lambda g:g.V().order().by('no').count())],
- 'g_V_properties_element': [(lambda g, xx1=None:g.V(xx1).properties().element()[0:1])],
- 'g_E_properties_element': [(lambda g, xx1=None:g.E(xx1).properties().element()[0:1])],
- 'g_V_properties_properties_element_element': [(lambda g, xx1=None:g.V(xx1).properties().properties().element().element()[0:1])],
+ 'g_VX1X_properties_element': [(lambda g, v2=None:g.V(v2).properties().element()[0:1])],
+ 'g_V_properties_element': [(lambda g:g.V().properties().element())],
+ 'g_V_propertiesXageX_element': [(lambda g:g.V().properties('age').element())],
+ 'g_EX_properties_element': [(lambda g, eid11=None:g.E(eid11).properties().element()[0:1])],
+ 'g_E_properties_element': [(lambda g:g.E().properties().element())],
+ 'g_VXv7_properties_properties_element_element': [(lambda g, v7=None:g.V(v7).properties().properties().element().element()[0:1])],
+ 'g_V_properties_properties_element_element': [(lambda g, v7=None:g.V(v7).properties().properties().element().element())],
'g_V_elementMap': [(lambda g:g.V().elementMap())],
'g_V_elementMapXname_ageX': [(lambda g:g.V().elementMap('name','age'))],
'g_EX11X_elementMap': [(lambda g, eid11=None:g.E(eid11).elementMap())],
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Element.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Element.feature
index a94e4bde31..6f5556d939 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Element.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Element.feature
@@ -19,41 +19,110 @@
Feature: Step - element()
# VertexProperty -> Vertex
+ Scenario: g_VX1X_properties_element
+ Given the modern graph
+ And using the parameter v2 defined as "v[josh]"
+ And the traversal of
+ """
+ g.V(v2).properties().element().limit(1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[josh] |
+
Scenario: g_V_properties_element
Given the modern graph
- And using the parameter xx1 defined as "v[josh]"
And the traversal of
"""
- g.V(xx1).properties().element().limit(1)
+ g.V().properties().element()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[marko] |
+ | v[vadas] |
+ | v[vadas] |
+ | v[lop] |
+ | v[lop] |
+ | v[josh] |
+ | v[josh] |
+ | v[ripple] |
+ | v[ripple] |
+ | v[peter] |
+ | v[peter] |
+
+ Scenario: g_V_propertiesXageX_element
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().properties("age").element()
"""
When iterated to list
Then the result should be unordered
| result |
+ | v[marko] |
+ | v[vadas] |
| v[josh] |
+ | v[peter] |
# EdgeProperty -> Edge
+ Scenario: g_EX_properties_element
+ Given the modern graph
+ And using the parameter eid11 defined as "e[josh-created->lop].id"
+ And the traversal of
+ """
+ g.E(eid11).properties().element().limit(1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[josh-created->lop] |
+
Scenario: g_E_properties_element
Given the modern graph
- And using the parameter xx1 defined as "e[josh-created->lop].id"
And the traversal of
"""
- g.E(xx1).properties().element().limit(1)
+ g.E().properties().element()
"""
When iterated to list
Then the result should be unordered
| result |
+ | e[marko-created->lop] |
+ | e[marko-knows->josh] |
+ | e[marko-knows->vadas] |
+ | e[peter-created->lop] |
| e[josh-created->lop] |
+ | e[josh-created->ripple] |
# MetaProperty -> VertexProperty
+ @MultiMetaProperties
+ Scenario: g_VXv7_properties_properties_element_element
+ Given the crew graph
+ And using the parameter v7 defined as "v[stephen]"
+ And the traversal of
+ """
+ g.V(v7).properties().properties().element().element().limit(1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[stephen] |
+
@MultiMetaProperties
Scenario: g_V_properties_properties_element_element
Given the crew graph
- And using the parameter xx1 defined as "v[stephen]"
+ And using the parameter v7 defined as "v[stephen]"
And the traversal of
"""
- g.V(xx1).properties().properties().element().element().limit(1)
+ g.V(v7).properties().properties().element().element()
"""
When iterated to list
Then the result should be unordered
| result |
+ | v[stephen] |
+ | v[stephen] |
+ | v[stephen] |
+ | v[stephen] |
| v[stephen] |
\ No newline at end of file