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
The following commit(s) were added to refs/heads/steps-taking-traversal-poc by
this push:
new 0acca58ff5 update to implement where(P)
0acca58ff5 is described below
commit 0acca58ff5618791699d7ab91a53033a7b2d12e5
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 e8f658f523..57c02cd13a 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 104ea4bb5c..ee2808eca5 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 65ccb0e94b..f34f594bf1 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 ac96cae8c4..00c93cd082 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 c993b1f6ed..e19bb62f0a 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 |