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"
