This is an automated email from the ASF dual-hosted git repository. xiazcy pushed a commit to branch steps-taking-traversal-poc in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 6aac8a0401193f40f476391002b75d8234c2e2f4 Author: Yang Xia <[email protected]> AuthorDate: Wed May 27 13:56:25 2026 -0700 update to implement where(P) --- .../traversal/step/filter/WherePredicateStep.java | 33 ++++- .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 7 ++ gremlin-go/driver/cucumber/gremlin.go | 7 ++ .../gremlin-javascript/test/cucumber/gremlin.js | 7 ++ .../src/main/python/tests/feature/gremlin.py | 7 ++ .../gremlin/language/translator/translations.json | 136 +++++++++++++++++++++ .../test/features/filter/WhereTraversal.feature | 122 ++++++++++++++++++ 7 files changed, 317 insertions(+), 2 deletions(-) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java index 77c3f4abc9..ce47519ea7 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java @@ -63,12 +63,15 @@ public final class WherePredicateStep<S> extends FilterStep<S> implements Scopin this.predicate = (P) predicate; this.selectKeys = new ArrayList<>(); this.configurePredicates(this.predicate); + // Integrate child traversals from the predicate so they participate in cloning/strategy application + P.integrateTraversals(this.predicate, this); } private void configurePredicates(final P<Object> predicate) { if (predicate instanceof ConnectiveP) ((ConnectiveP<Object>) predicate).getPredicates().forEach(this::configurePredicates); - else { + else if (!predicate.hasTraversal()) { + // Only configure scope keys for non-traversal predicates (string label references) final String selectKey = getSelectKey(predicate); this.selectKeys.add(selectKey); this.scopeKeys.add(selectKey); @@ -112,6 +115,27 @@ public final class WherePredicateStep<S> extends FilterStep<S> implements Scopin @Override protected boolean filter(final Traverser.Admin<S> traverser) { + // If the predicate has a child traversal, resolve it and test directly against the + // current value (or startKey scope value). This bypasses the scope-label mechanism. + if (this.predicate.hasTraversal()) { + final Object leftValue; + if (null == this.startKey) { + final TraversalProduct product = TraversalUtil.produce(traverser, this.traversalRing.next()); + this.traversalRing.reset(); + if (!product.isProductive()) return false; + leftValue = product.get(); + } else { + final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, this.startKey, traverser), this.traversalRing.next()); + this.traversalRing.reset(); + if (!product.isProductive()) return false; + leftValue = product.get(); + } + this.predicate.resolve(traverser); + if (this.predicate.isResolvedEmpty()) return false; + return this.predicate.test(leftValue); + } + + // Standard scope-label path for non-traversal predicates final TraversalProduct product = null == this.startKey ? TraversalUtil.produce(traverser, this.traversalRing.next()) : TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, this.startKey, traverser), this.traversalRing.next()); @@ -166,7 +190,12 @@ public final class WherePredicateStep<S> extends FilterStep<S> implements Scopin @Override public List<Traversal.Admin<S, ?>> getLocalChildren() { - return (List) this.traversalRing.getTraversals(); + final List<Traversal.Admin<S, ?>> children = new ArrayList<>((List) this.traversalRing.getTraversals()); + // Also expose predicate child traversals for strategy application and cloning + final List<Traversal.Admin<?, ?>> predicateTraversals = new ArrayList<>(); + P.collectTraversals(this.predicate, predicateTraversals); + children.addAll((List) predicateTraversals); + return children; } @Override diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs index d460dcadeb..e54133e1f0 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs @@ -773,6 +773,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin {"get_g_V_whereXage_isXgt_30XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Where(__.Values<object>("age").Is(P.Gt(30)))}}, {"g_V_whereXlabel_isXsoftwareXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Where(__.Label().Is("software"))}}, {"g_V_whereXlabel_isXpersonXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Where(__.Label().Is("person"))}}, + {"g_V_valuesXageX_whereXgtXVXvid1X_valuesXageXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Where(P.Gt(__.V(p["vid1"]).Values<object>("age")))}}, + {"g_V_valuesXageX_whereXltXVXvid3X_valuesXageXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Where(P.Lt(__.V(p["vid3"]).Values<object>("age")))}}, + {"g_V_valuesXageX_whereXeqXVXvid1X_valuesXageXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Where(P.Eq(__.V(p["vid1"]).Values<object>("age")))}}, + {"g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Where(P.Within(__.V(p["vid1"]).Out("knows").Values<object>("age")))}}, + {"g_V_valuesXnameX_whereXneqXVXvid1X_valuesXnameXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Where(P.Neq(__.V(p["vid1"]).Values<object>("name")))}}, + {"g_V_valuesXageX_whereXeqXV9999_valuesXageXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Where(P.Eq(__.V(9999).Values<object>("age")))}}, + {"g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Where(P.Gt(__.V(p["vid1"]).Values<object>("age"))).By("age").Values<object>("name")}}, {"g_withStrategiesXAdjacentToIncidentStrategyX_V", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new AdjacentToIncidentStrategy()).V()}}, {"g_withoutStrategiesXAdjacentToIncidentStrategyX_V", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithoutStrategies(typeof(AdjacentToIncidentStrategy)).V()}}, {"g_withStrategiesXAdjacentToIncidentStrategyX_V_out_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new AdjacentToIncidentStrategy()).V().Out().Count()}}, diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go index 60808e97d4..9003f7b3f8 100644 --- a/gremlin-go/driver/cucumber/gremlin.go +++ b/gremlin-go/driver/cucumber/gremlin.go @@ -743,6 +743,13 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "get_g_V_whereXage_isXgt_30XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.Values("age").Is(gremlingo.P.Gt(30)))}}, "g_V_whereXlabel_isXsoftwareXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.Label().Is("software"))}}, "g_V_whereXlabel_isXpersonXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.Label().Is("person"))}}, + "g_V_valuesXageX_whereXgtXVXvid1X_valuesXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Gt(gremlingo.T__.V(p["vid1"]).Values("age")))}}, + "g_V_valuesXageX_whereXltXVXvid3X_valuesXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Lt(gremlingo.T__.V(p["vid3"]).Values("age")))}}, + "g_V_valuesXageX_whereXeqXVXvid1X_valuesXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Eq(gremlingo.T__.V(p["vid1"]).Values("age")))}}, + "g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Within(gremlingo.T__.V(p["vid1"]).Out("knows").Values("age")))}}, + "g_V_valuesXnameX_whereXneqXVXvid1X_valuesXnameXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Where(gremlingo.P.Neq(gremlingo.T__.V(p["vid1"]).Values("name")))}}, + "g_V_valuesXageX_whereXeqXV9999_valuesXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Eq(gremlingo.T__.V(9999).Values("age")))}}, + "g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.P.Gt(gremlingo.T__.V(p["vid1"]).Values("age"))).By("age").Values("name")}}, "g_withStrategiesXAdjacentToIncidentStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.AdjacentToIncidentStrategy()).V()}}, "g_withoutStrategiesXAdjacentToIncidentStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.AdjacentToIncidentStrategy()).V()}}, "g_withStrategiesXAdjacentToIncidentStrategyX_V_out_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.AdjacentToIncidentStrategy()).V().Out().Count()}}, diff --git a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js index c2a1640ae4..1d705754b8 100644 --- a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js +++ b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js @@ -774,6 +774,13 @@ const gremlins = { get_g_V_whereXage_isXgt_30XX: [function({g}) { return g.V().where(__.values("age").is(P.gt(30))) }], g_V_whereXlabel_isXsoftwareXX: [function({g}) { return g.V().where(__.label().is("software")) }], g_V_whereXlabel_isXpersonXX: [function({g}) { return g.V().where(__.label().is("person")) }], + g_V_valuesXageX_whereXgtXVXvid1X_valuesXageXXX: [function({g, vid1}) { return g.V().values("age").where(P.gt(__.V(vid1).values("age"))) }], + g_V_valuesXageX_whereXltXVXvid3X_valuesXageXXX: [function({g, vid3}) { return g.V().values("age").where(P.lt(__.V(vid3).values("age"))) }], + g_V_valuesXageX_whereXeqXVXvid1X_valuesXageXXX: [function({g, vid1}) { return g.V().values("age").where(P.eq(__.V(vid1).values("age"))) }], + g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX: [function({g, vid1}) { return g.V().values("age").where(P.within(__.V(vid1).out("knows").values("age"))) }], + g_V_valuesXnameX_whereXneqXVXvid1X_valuesXnameXXX: [function({g, vid1}) { return g.V().values("name").where(P.neq(__.V(vid1).values("name"))) }], + g_V_valuesXageX_whereXeqXV9999_valuesXageXXX: [function({g}) { return g.V().values("age").where(P.eq(__.V(9999).values("age"))) }], + g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX: [function({g, vid1}) { return g.V().where(P.gt(__.V(vid1).values("age"))).by("age").values("name") }], g_withStrategiesXAdjacentToIncidentStrategyX_V: [function({g}) { return g.withStrategies(new AdjacentToIncidentStrategy()).V() }], g_withoutStrategiesXAdjacentToIncidentStrategyX_V: [function({g}) { return g.withoutStrategies(AdjacentToIncidentStrategy).V() }], g_withStrategiesXAdjacentToIncidentStrategyX_V_out_count: [function({g}) { return g.withStrategies(new AdjacentToIncidentStrategy()).V().out().count() }], diff --git a/gremlin-python/src/main/python/tests/feature/gremlin.py b/gremlin-python/src/main/python/tests/feature/gremlin.py index aa4358cfe7..5928aaedc4 100644 --- a/gremlin-python/src/main/python/tests/feature/gremlin.py +++ b/gremlin-python/src/main/python/tests/feature/gremlin.py @@ -748,6 +748,13 @@ world.gremlins = { 'get_g_V_whereXage_isXgt_30XX': [(lambda g:g.V().where(__.values('age').is_(P.gt(30))))], 'g_V_whereXlabel_isXsoftwareXX': [(lambda g:g.V().where(__.label().is_('software')))], 'g_V_whereXlabel_isXpersonXX': [(lambda g:g.V().where(__.label().is_('person')))], + 'g_V_valuesXageX_whereXgtXVXvid1X_valuesXageXXX': [(lambda g, vid1=None:g.V().values('age').where(P.gt(__.V(vid1).values('age'))))], + 'g_V_valuesXageX_whereXltXVXvid3X_valuesXageXXX': [(lambda g, vid3=None:g.V().values('age').where(P.lt(__.V(vid3).values('age'))))], + 'g_V_valuesXageX_whereXeqXVXvid1X_valuesXageXXX': [(lambda g, vid1=None:g.V().values('age').where(P.eq(__.V(vid1).values('age'))))], + 'g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX': [(lambda g, vid1=None:g.V().values('age').where(P.within(__.V(vid1).out('knows').values('age'))))], + 'g_V_valuesXnameX_whereXneqXVXvid1X_valuesXnameXXX': [(lambda g, vid1=None:g.V().values('name').where(P.neq(__.V(vid1).values('name'))))], + 'g_V_valuesXageX_whereXeqXV9999_valuesXageXXX': [(lambda g:g.V().values('age').where(P.eq(__.V(9999).values('age'))))], + 'g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX': [(lambda g, vid1=None:g.V().where(P.gt(__.V(vid1).values('age'))).by('age').values('name'))], 'g_withStrategiesXAdjacentToIncidentStrategyX_V': [(lambda g:g.with_strategies(AdjacentToIncidentStrategy()).V())], 'g_withoutStrategiesXAdjacentToIncidentStrategyX_V': [(lambda g:g.without_strategies(AdjacentToIncidentStrategy).V())], 'g_withStrategiesXAdjacentToIncidentStrategyX_V_out_count': [(lambda g:g.with_strategies(AdjacentToIncidentStrategy()).V().out().count())], diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json index 99148d3a53..1340ec569c 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json @@ -6516,6 +6516,23 @@ } ] }, + { + "scenario": "g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected", + "traversals": [ + { + "original": "g.V().property(__.addV(\"temp\").project(\"k\").by(\"name\"))", + "language": "g.V().property(__.addV(\"temp\").project(\"k\").by(\"name\"))", + "canonical": "g.V().property(__.addV(\"temp\").project(\"k\").by(\"name\"))", + "anonymized": "g.V().property(__.addV(string0).project(string1).by(string2))", + "dotnet": "g.V().Property((ITraversal) __.AddV((string) \"temp\").Project<object>(\"k\").By(\"name\"))", + "go": "g.V().Property(gremlingo.T__.AddV(\"temp\").Project(\"k\").By(\"name\"))", + "groovy": "g.V().property(__.addV(\"temp\").project(\"k\").by(\"name\"))", + "java": "g.V().property(__.addV(\"temp\").project(\"k\").by(\"name\"))", + "javascript": "g.V().property(__.addV(\"temp\").project(\"k\").by(\"name\"))", + "python": "g.V().property(__.add_v('temp').project('k').by('name'))" + } + ] + }, { "scenario": "g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification", "traversals": [ @@ -13359,6 +13376,125 @@ } ] }, + { + "scenario": "g_V_valuesXageX_whereXgtXVXvid1X_valuesXageXXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.gt(__.V(vid1).values(\"age\")))", + "language": "g.V().values(\"age\").where(P.gt(__.V(vid1).values(\"age\")))", + "canonical": "g.V().values(\"age\").where(P.gt(__.V(vid1).values(\"age\")))", + "anonymized": "g.V().values(string0).where(P.gt(__.V(vid1).values(string0)))", + "dotnet": "g.V().Values<object>(\"age\").Where(P.Gt(__.V(vid1).Values<object>(\"age\")))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Gt(gremlingo.T__.V(vid1).Values(\"age\")))", + "groovy": "g.V().values(\"age\").where(P.gt(__.V(vid1).values(\"age\")))", + "java": "g.V().values(\"age\").where(P.gt(__.V(vid1).values(\"age\")))", + "javascript": "g.V().values(\"age\").where(P.gt(__.V(vid1).values(\"age\")))", + "python": "g.V().values('age').where(P.gt(__.V(vid1).values('age')))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXltXVXvid3X_valuesXageXXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.lt(__.V(vid3).values(\"age\")))", + "language": "g.V().values(\"age\").where(P.lt(__.V(vid3).values(\"age\")))", + "canonical": "g.V().values(\"age\").where(P.lt(__.V(vid3).values(\"age\")))", + "anonymized": "g.V().values(string0).where(P.lt(__.V(vid3).values(string0)))", + "dotnet": "g.V().Values<object>(\"age\").Where(P.Lt(__.V(vid3).Values<object>(\"age\")))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Lt(gremlingo.T__.V(vid3).Values(\"age\")))", + "groovy": "g.V().values(\"age\").where(P.lt(__.V(vid3).values(\"age\")))", + "java": "g.V().values(\"age\").where(P.lt(__.V(vid3).values(\"age\")))", + "javascript": "g.V().values(\"age\").where(P.lt(__.V(vid3).values(\"age\")))", + "python": "g.V().values('age').where(P.lt(__.V(vid3).values('age')))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXeqXVXvid1X_valuesXageXXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.eq(__.V(vid1).values(\"age\")))", + "language": "g.V().values(\"age\").where(P.eq(__.V(vid1).values(\"age\")))", + "canonical": "g.V().values(\"age\").where(P.eq(__.V(vid1).values(\"age\")))", + "anonymized": "g.V().values(string0).where(P.eq(__.V(vid1).values(string0)))", + "dotnet": "g.V().Values<object>(\"age\").Where(P.Eq(__.V(vid1).Values<object>(\"age\")))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Eq(gremlingo.T__.V(vid1).Values(\"age\")))", + "groovy": "g.V().values(\"age\").where(P.eq(__.V(vid1).values(\"age\")))", + "java": "g.V().values(\"age\").where(P.eq(__.V(vid1).values(\"age\")))", + "javascript": "g.V().values(\"age\").where(P.eq(__.V(vid1).values(\"age\")))", + "python": "g.V().values('age').where(P.eq(__.V(vid1).values('age')))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\")))", + "language": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\")))", + "canonical": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\")))", + "anonymized": "g.V().values(string0).where(P.within(__.V(vid1).out(string1).values(string0)))", + "dotnet": "g.V().Values<object>(\"age\").Where(P.Within(__.V(vid1).Out(\"knows\").Values<object>(\"age\")))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Within(gremlingo.T__.V(vid1).Out(\"knows\").Values(\"age\")))", + "groovy": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\")))", + "java": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\")))", + "javascript": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\")))", + "python": "g.V().values('age').where(P.within(__.V(vid1).out('knows').values('age')))" + } + ] + }, + { + "scenario": "g_V_valuesXnameX_whereXneqXVXvid1X_valuesXnameXXX", + "traversals": [ + { + "original": "g.V().values(\"name\").where(P.neq(__.V(vid1).values(\"name\")))", + "language": "g.V().values(\"name\").where(P.neq(__.V(vid1).values(\"name\")))", + "canonical": "g.V().values(\"name\").where(P.neq(__.V(vid1).values(\"name\")))", + "anonymized": "g.V().values(string0).where(P.neq(__.V(vid1).values(string0)))", + "dotnet": "g.V().Values<object>(\"name\").Where(P.Neq(__.V(vid1).Values<object>(\"name\")))", + "go": "g.V().Values(\"name\").Where(gremlingo.P.Neq(gremlingo.T__.V(vid1).Values(\"name\")))", + "groovy": "g.V().values(\"name\").where(P.neq(__.V(vid1).values(\"name\")))", + "java": "g.V().values(\"name\").where(P.neq(__.V(vid1).values(\"name\")))", + "javascript": "g.V().values(\"name\").where(P.neq(__.V(vid1).values(\"name\")))", + "python": "g.V().values('name').where(P.neq(__.V(vid1).values('name')))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXeqXV9999_valuesXageXXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.eq(__.V(9999).values(\"age\")))", + "language": "g.V().values(\"age\").where(P.eq(__.V(9999).values(\"age\")))", + "canonical": "g.V().values(\"age\").where(P.eq(__.V(9999).values(\"age\")))", + "anonymized": "g.V().values(string0).where(P.eq(__.V(number0).values(string0)))", + "dotnet": "g.V().Values<object>(\"age\").Where(P.Eq(__.V(9999).Values<object>(\"age\")))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Eq(gremlingo.T__.V(9999).Values(\"age\")))", + "groovy": "g.V().values(\"age\").where(P.eq(__.V(9999).values(\"age\")))", + "java": "g.V().values(\"age\").where(P.eq(__.V(9999).values(\"age\")))", + "javascript": "g.V().values(\"age\").where(P.eq(__.V(9999).values(\"age\")))", + "python": "g.V().values('age').where(P.eq(__.V(9999).values('age')))" + } + ] + }, + { + "scenario": "g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX", + "traversals": [ + { + "original": "g.V().where(P.gt(__.V(vid1).values(\"age\"))).by(\"age\").values(\"name\")", + "language": "g.V().where(P.gt(__.V(vid1).values(\"age\"))).by(\"age\").values(\"name\")", + "canonical": "g.V().where(P.gt(__.V(vid1).values(\"age\"))).by(\"age\").values(\"name\")", + "anonymized": "g.V().where(P.gt(__.V(vid1).values(string0))).by(string0).values(string1)", + "dotnet": "g.V().Where(P.Gt(__.V(vid1).Values<object>(\"age\"))).By(\"age\").Values<object>(\"name\")", + "go": "g.V().Where(gremlingo.P.Gt(gremlingo.T__.V(vid1).Values(\"age\"))).By(\"age\").Values(\"name\")", + "groovy": "g.V().where(P.gt(__.V(vid1).values(\"age\"))).by(\"age\").values(\"name\")", + "java": "g.V().where(P.gt(__.V(vid1).values(\"age\"))).by(\"age\").values(\"name\")", + "javascript": "g.V().where(P.gt(__.V(vid1).values(\"age\"))).by(\"age\").values(\"name\")", + "python": "g.V().where(P.gt(__.V(vid1).values('age'))).by('age').values('name')" + } + ] + }, { "scenario": "g_withStrategiesXAdjacentToIncidentStrategyX_V", "traversals": [ diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/WhereTraversal.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/WhereTraversal.feature new file mode 100644 index 0000000000..cf9628883a --- /dev/null +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/WhereTraversal.feature @@ -0,0 +1,122 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +@StepClassFilter @StepWhere +Feature: Step - where(P) with traversal-bearing predicates + + # where(P.gt(traversal)) — compare current traverser value against resolved traversal result + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_valuesXageX_whereXgtXVXvid1X_valuesXageXXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().values("age").where(P.gt(__.V(vid1).values("age"))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[32].i | + | d[35].i | + + # where(P.lt(traversal)) — filter ages less than josh's age + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_valuesXageX_whereXltXVXvid3X_valuesXageXXX + Given the modern graph + And using the parameter vid3 defined as "v[josh].id" + And the traversal of + """ + g.V().values("age").where(P.lt(__.V(vid3).values("age"))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | + | d[27].i | + + # where(P.eq(traversal)) — exact match against resolved value + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_valuesXageX_whereXeqXVXvid1X_valuesXageXXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().values("age").where(P.eq(__.V(vid1).values("age"))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | + + # where(P.within(traversal)) — collection membership against resolved traversal results + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().values("age").where(P.within(__.V(vid1).out("knows").values("age"))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[27].i | + | d[32].i | + + # where(P.neq(traversal)) — not equal to resolved value + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_valuesXnameX_whereXneqXVXvid1X_valuesXnameXXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().values("name").where(P.neq(__.V(vid1).values("name"))) + """ + When iterated to list + Then the result should be unordered + | result | + | vadas | + | lop | + | josh | + | ripple | + | peter | + + # Empty traversal result — filters out (no match) + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_valuesXageX_whereXeqXV9999_valuesXageXXX + Given the modern graph + And the traversal of + """ + g.V().values("age").where(P.eq(__.V(9999).values("age"))) + """ + When iterated to list + Then the result should be empty + + # where(P.gt(traversal)) with by() modulator — compare property values + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().where(P.gt(__.V(vid1).values("age"))).by("age").values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | josh | + | peter |
