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

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

commit db7865ae8ff1cacb1b73752f4526ee2d9f03dd30
Author: Stephen Mallette <[email protected]>
AuthorDate: Mon Aug 26 18:02:11 2024 -0400

    wip - added param to has(string, string, object)
---
 .../language/grammar/TraversalMethodVisitor.java   | 13 +++++++++---
 .../traversal/dsl/graph/GraphTraversal.java        | 16 +++++++++++++++
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  2 ++
 gremlin-go/driver/cucumber/gremlin.go              |  2 ++
 .../gremlin-javascript/test/cucumber/gremlin.js    |  2 ++
 gremlin-python/src/main/python/radish/gremlin.py   |  2 ++
 .../gremlin/test/features/filter/Has.feature       | 24 ++++++++++++++++++++++
 7 files changed, 58 insertions(+), 3 deletions(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 38aa65f6b2..ce010e326e 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -836,9 +836,16 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
      */
     @Override
     public GraphTraversal visitTraversalMethod_has_String_String_Object(final 
GremlinParser.TraversalMethod_has_String_String_ObjectContext ctx) {
-        return 
graphTraversal.has(antlr.argumentVisitor.parseString(ctx.stringNullableArgument(0)),
-                
antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
-                
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+        final Object literalOrVar = 
antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument(0));
+        if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+            return graphTraversal.has((GValue) literalOrVar,
+                    
antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
+                    
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+        } else {
+            return graphTraversal.has((String) literalOrVar,
+                    
antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
+                    
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+        }
     }
 
     /**
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 6342c981c6..5cf66f4d6c 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
@@ -684,6 +684,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, 
E> {
             return this.asAdmin().addStep(step);
         }
 
+        /**
+         * Filters vertices, edges and vertex properties based on their 
properties.
+         *
+         * @param label       the label of the {@link Element}
+         * @param propertyKey the key of the property to filter on
+         * @param value       the value to compare the accessor value to for 
equality
+         * @return the traversal with an appended {@link HasStep}
+         * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step"; 
target="_blank">Reference Documentation - Has Step</a>
+         * @since 4.0.0
+         */
+        public default GraphTraversal<S, E> has(final GValue<String> label, 
final String propertyKey, final Object value) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.has, 
label.get(), propertyKey, value);
+            TraversalHelper.addHasContainer(this.asAdmin(), new 
HasContainer(T.label.getAccessor(), P.eq(label)));
+            return TraversalHelper.addHasContainer(this.asAdmin(), new 
HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value)));
+        }
+
         @Override
         public default <E2> GraphTraversal.Admin<S, E2> addStep(final Step<?, 
E2> step) {
             return (GraphTraversal.Admin<S, E2>) 
Traversal.Admin.super.addStep((Step) step);
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 49eb11fe5d..b324e8be68 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -234,6 +234,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_VX1X_out_hasXid_2X", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) 
p["v2"]).Has("age", P.Gt(30))}}, 
                {"g_V_hasXblahX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("blah")}}, 
                {"g_V_hasXperson_name_markoX_age", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Has("person", "name", "marko").Values<object>("age")}}, 
+               {"g_V_hasXperson_name_markovarX_age", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Has("person", "name", (object) 
p["xx1"]).Values<object>("age")}}, 
+               {"g_V_hasXpersonvar_name_markoX_age", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Has((string) p["xx1"], "name", "marko").Values<object>("age")}}, 
                {"g_VX1X_outE_hasXweight_inside_0_06X_inV", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(p["vid1"]).OutE().Has("weight", P.Inside(0.0, 0.6)).InV()}}, 
                {"g_EX11X_outV_outE_hasXid_10X", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.E(p["eid11"]).OutV().OutE().Has(T.Id, (object) p["eid10"])}}, 
                {"g_EX11X_outV_outE_hasXid_10AsStringX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.E(p["eid11"]).OutV().OutE().Has(T.Id, (object) p["eid10"])}}, 
diff --git a/gremlin-go/driver/cucumber/gremlin.go 
b/gremlin-go/driver/cucumber/gremlin.go
index 449783b0f4..667ae6d1f3 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -204,6 +204,8 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_VX1X_out_hasXid_2X": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V(p["v2"]).Has("age", gremlingo.P.Gt(30))}}, 
     "g_V_hasXblahX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("blah")}}, 
     "g_V_hasXperson_name_markoX_age": {func(g *gremlingo.GraphTraversalSource, 
p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", 
"name", "marko").Values("age")}}, 
+    "g_V_hasXperson_name_markovarX_age": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has("person", "name", 
p["xx1"]).Values("age")}}, 
+    "g_V_hasXpersonvar_name_markoX_age": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has(p["xx1"], "name", 
"marko").Values("age")}}, 
     "g_VX1X_outE_hasXweight_inside_0_06X_inV": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V(p["vid1"]).OutE().Has("weight", 
gremlingo.P.Inside(0.0, 0.6)).InV()}}, 
     "g_EX11X_outV_outE_hasXid_10X": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.E(p["eid11"]).OutV().OutE().Has(gremlingo.T.Id, p["eid10"])}}, 
     "g_EX11X_outV_outE_hasXid_10AsStringX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.E(p["eid11"]).OutV().OutE().Has(gremlingo.T.Id, p["eid10"])}}, 
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 273d2b6da8..d381f1a8da 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
@@ -225,6 +225,8 @@ const gremlins = {
     g_VX1X_out_hasXid_2X: [function({g, v2}) { return g.V(v2).has("age", 
P.gt(30)) }], 
     g_V_hasXblahX: [function({g}) { return g.V().has("blah") }], 
     g_V_hasXperson_name_markoX_age: [function({g}) { return 
g.V().has("person", "name", "marko").values("age") }], 
+    g_V_hasXperson_name_markovarX_age: [function({g, xx1}) { return 
g.V().has("person", "name", xx1).values("age") }], 
+    g_V_hasXpersonvar_name_markoX_age: [function({g, xx1}) { return 
g.V().has(xx1, "name", "marko").values("age") }], 
     g_VX1X_outE_hasXweight_inside_0_06X_inV: [function({g, vid1}) { return 
g.V(vid1).outE().has("weight", P.inside(0.0, 0.6)).inV() }], 
     g_EX11X_outV_outE_hasXid_10X: [function({g, eid11, eid10}) { return 
g.E(eid11).outV().outE().has(T.id, eid10) }], 
     g_EX11X_outV_outE_hasXid_10AsStringX: [function({g, eid11, eid10}) { 
return g.E(eid11).outV().outE().has(T.id, eid10) }], 
diff --git a/gremlin-python/src/main/python/radish/gremlin.py 
b/gremlin-python/src/main/python/radish/gremlin.py
index 044b366215..f5e906f5d1 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -207,6 +207,8 @@ world.gremlins = {
     'g_VX1X_out_hasXid_2X': [(lambda g, v2=None:g.V(v2).has('age', 
P.gt(30)))], 
     'g_V_hasXblahX': [(lambda g:g.V().has('blah'))], 
     'g_V_hasXperson_name_markoX_age': [(lambda g:g.V().has('person', 'name', 
'marko').values('age'))], 
+    'g_V_hasXperson_name_markovarX_age': [(lambda g, 
xx1=None:g.V().has('person', 'name', xx1).values('age'))], 
+    'g_V_hasXpersonvar_name_markoX_age': [(lambda g, xx1=None:g.V().has(xx1, 
'name', 'marko').values('age'))], 
     'g_VX1X_outE_hasXweight_inside_0_06X_inV': [(lambda g, 
vid1=None:g.V(vid1).out_e().has('weight', P.inside(0.0, 0.6)).in_v())], 
     'g_EX11X_outV_outE_hasXid_10X': [(lambda g, 
eid11=None,eid10=None:g.E(eid11).out_v().out_e().has(T.id_, eid10))], 
     'g_EX11X_outV_outE_hasXid_10AsStringX': [(lambda g, 
eid11=None,eid10=None:g.E(eid11).out_v().out_e().has(T.id_, eid10))], 
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
index c10757748d..8a1db09a05 100644
--- 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
@@ -206,6 +206,30 @@ Feature: Step - has()
       | result |
       | d[29].i |
 
+  Scenario: g_V_hasXperson_name_markovarX_age
+    Given the modern graph
+    And using the parameter xx1 defined as "marko"
+    And the traversal of
+    """
+    g.V().has("person", "name", xx1).values("age")
+    """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[29].i |
+
+  Scenario: g_V_hasXpersonvar_name_markoX_age
+    Given the modern graph
+    And using the parameter xx1 defined as "person"
+    And the traversal of
+    """
+    g.V().has(xx1, "name", "marko").values("age")
+    """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[29].i |
+
   Scenario: g_VX1X_outE_hasXweight_inside_0_06X_inV
     Given the modern graph
     And using the parameter vid1 defined as "v[marko].id"

Reply via email to