diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index c77c4062b9b..963ad54f5c0 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -91,6 +91,15 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima * Added transaction closure methods (`executeInTx`/`evaluateInTx`) on `GraphTraversalSource` in all GLVs that wrap the begin/commit/rollback lifecycle, so a lambda receives the transaction-bound `g` and is auto-committed on success or rolled back on error. * Changed default transaction close behavior from commit to rollback across all GLVs to align with embedded graph defaults. * Refactored Go driver connection to block until response headers arrive, enabling synchronous error returns and proper transaction ordering. +* Added child traversal support to `has()`, `hasLabel()`, `V()`, `E()`, `property()`, `is()`, `where(P)`, `P.eq/neq/gt/lt/gte/lte/within/without()`, and `TextP` predicates. Child traversals are resolved per-traverser at runtime, enabling dynamic filtering and lookup patterns. +* Added multi-traversal `P.within(trav1, trav2, ...)` and `P.without(trav1, trav2, ...)` which combine results from multiple child traversals for collection membership testing. +* Added `V(traversal)` and `E(traversal)` as start steps with synthetic traverser seeding, consistent with `mergeV(traversal)` behavior. +* Added `ReadOnlyChildVerificationStrategy` that blocks mutating steps (`addV`, `addE`, `drop`, etc.) inside child traversals. All child traversals must be read-only. +* Added `hasLabel(Traversal)` overload with grammar support for dynamic label filtering. +* Added traversal-bearing predicate support to `where(P)` - resolves child traversal and tests against current value when `P.hasTraversal()` is true. +* Added rejection of traversal-bearing predicates in `choose(P)` and `choose().option(P, ...)` - the predicate's child traversal cannot be resolved in the branch-selection context. +* Added runtime Map validation for `property(traversal)` - rejects results that are not a `Map` of property key/value pairs. +* Added mixed traversal/literal detection in `P.within()` and `P.without()` - throws `IllegalArgumentException` with guidance to wrap literals in `__.constant()`. * Removed `uuid` dependency from `gremlin-javascript` in favor of the built-in `globalThis.crypto.randomUUID()`. * Added streaming HTTP response support to `gremlin-driver` for incremental result deserialization over GraphBinary. * Connected HTTP streaming response deserialization to the traversal API in `gremlin-javascript`, enabling `next()` to return the first result without waiting for the full response. diff --git a/docs/src/dev/provider/gremlin-semantics.asciidoc b/docs/src/dev/provider/gremlin-semantics.asciidoc index 401d90cdf5c..8b25408ff29 100644 --- a/docs/src/dev/provider/gremlin-semantics.asciidoc +++ b/docs/src/dev/provider/gremlin-semantics.asciidoc @@ -1585,6 +1585,45 @@ None See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementStep.java[source], link:https://tinkerpop.apache.org/docs/x.y.z/reference/#element-step[reference] +[[e-step]] +=== E() + +*Description:* Reads edges from the graph by their identifiers. Can be used as a start step or mid-traversal. + +*Syntax:* `E(edgeIds: any...)` | `E(idTraversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|Y |Y |N |`any` |`Edge` +|========================================================= + +*Arguments:* + +* `edgeIds` - Zero or more edge identifiers. If none are provided, all edges are returned. Arrays and list-valued + arguments are flattened (unrolled) into individual IDs. +* `idTraversal` - A child traversal which supplies edge identifiers. The child traversal must be read-only + (no mutating steps). + +*Modulation:* + +None + +*Considerations:* + +* When used as a start step with a traversal argument, a synthetic traverser seeds the child traversal. +* When used mid-traversal with a traversal argument, the current traverser seeds the child traversal. +* If no edges match the provided identifiers, the step produces no results. +* Graph providers may optimize `E()` with subsequent `has()` filters by folding `HasContainer` predicates into the + step for index-backed lookups. + +*Exceptions:* + +None + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#graph-step[reference] + [[format-step]] === format() @@ -1703,6 +1742,204 @@ See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/j link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java[source (sideEffect)], link:https://tinkerpop.apache.org/docs/x.y.z/reference/#groupcount-step[reference] +[[has-step]] +=== has() + +*Description:* Filters traversers by property existence, property value, label, or identifier. + +*Syntax:* `has(key: STRING)` | `has(key: STRING, value: any)` | `has(key: STRING, predicate: P)` | `has(key: STRING, traversal: Traversal)` | `has(accessor: T, value: any)` | `has(accessor: T, predicate: P)` | `has(accessor: T, traversal: Traversal)` | `has(label: STRING, key: STRING, value: any)` | `has(label: STRING, key: STRING, predicate: P)` | `has(label: STRING, key: STRING, traversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |N |`Element` / `Property` |`Element` / `Property` +|========================================================= + +*Arguments:* + +* `key` - The property key to check. +* `accessor` - A `T` accessor: `T.id` (element identifier), `T.label` (element label), `T.key` (property key), or + `T.value` (property value). +* `value` - The value to compare against using equality. +* `predicate` - A `P` predicate for comparison. The predicate value may be a literal or a `Traversal`. +* `traversal` - A child traversal whose first result is used as the comparison value (implicitly wrapped in `P.eq()`). + Must be read-only (no mutating steps). The child traversal is evaluated per-traverser: the current traverser seeds + the child, and the first result is used for comparison. +* `label` - A label filter applied before the property check (three-argument form). + +*Modulation:* + +None + +*Considerations:* + +* `has(key)` filters to elements that have the specified property (existence check). +* `has(T.label, value)` is equivalent to `hasLabel(value)`. `has(T.id, value)` is equivalent to `hasId(value)`. +* When the domain is a `Property` (e.g., from `properties()`), `T.key` and `T.value` accessors are used to filter + by property key or property value respectively. +* When the predicate value for `T.id` is a `STRING`, the element's `id().toString()` is used for comparison. +* For multi-valued properties (list/set cardinality), `has(key, value)` passes if *any* property with that key matches. +* When a `Traversal` is supplied as a value or inside a `P`, it is resolved per-traverser and its first result is used. +* Child traversals must be read-only. Mutating steps are rejected with an `Argument Error`. +* `has(key, null)` filters to elements where the property value is `null` (not an existence check). +* `has(null)` and `has(null, value)` always produce an empty result. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. +* A `State Error` is raised if the traverser is not an `Element` or `Property`. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[reference] + +[[hasid-step]] +=== hasId() + +*Description:* Filters elements by their identifier. + +*Syntax:* `hasId(id: any, otherIds: any...)` | `hasId(predicate: P)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |N |`Element` |`Element` +|========================================================= + +*Arguments:* + +* `id` - One or more identifiers, or Traversals supplying identifiers to match against. Arrays and list-valued + arguments are flattened (unrolled) into individual IDs. Multiple IDs are combined into `P.within(...)`. +* `predicate` - A `P` predicate for identifier comparison. The predicate value may contain a `Traversal`. + +*Modulation:* + +None + +*Considerations:* + +* Equivalent to `has(T.id, ...)`. +* When the predicate value is a `STRING`, the element's `id().toString()` is used for comparison. +* `hasId(null)` filters all elements since `T.id` cannot be null. +* Child traversals must be read-only; mutating steps are rejected with an `Argument Error`. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[reference] + +[[haskey-step]] +=== hasKey() + +*Description:* Filters properties by their key. + +*Syntax:* `hasKey(key: STRING, otherKeys: STRING...)` | `hasKey(predicate: P)` | `hasKey(traversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |N |`Property` / `VertexProperty` |`Property` / `VertexProperty` +|========================================================= + +*Arguments:* + +* `key` - One or more keys to match against. +* `predicate` - A `P` predicate for key comparison. The predicate value may contain a `Traversal`. +* `traversal` - A child traversal whose first result is used as the key (implicitly wrapped in `P.eq()`). + Must be read-only. + +*Modulation:* + +None + +*Considerations:* + +* Equivalent to `has(T.key, ...)`. +* Operates on `Property` or `VertexProperty` traversers (typically reached via `properties()`). +* Not intended for testing key existence on vertices/edges, use `has(key)` for that purpose. +* Child traversals must be read-only; mutating steps are rejected with an `Argument Error`. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[reference] + +[[haslabel-step]] +=== hasLabel() + +*Description:* Filters elements by their label. + +*Syntax:* `hasLabel(label: STRING, otherLabels: STRING...)` | `hasLabel(predicate: P)` | `hasLabel(traversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |N |`Element` |`Element` +|========================================================= + +*Arguments:* + +* `label` - One or more labels to match against. +* `predicate` - A `P` predicate for label comparison. The predicate value may contain a `Traversal`. +* `traversal` - A child traversal whose first result is used as the label (implicitly wrapped in `P.eq()`). + Must be read-only. + +*Modulation:* + +None + +*Considerations:* + +* Equivalent to `has(T.label, ...)`. +* Child traversals must be read-only; mutating steps are rejected with an `Argument Error`. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[reference] + +[[hasvalue-step]] +=== hasValue() + +*Description:* Filters properties by their value. + +*Syntax:* `hasValue(value: any, otherValues: any...)` | `hasValue(predicate: P)` | `hasValue(traversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |N |`Property` / `VertexProperty` |`Property` / `VertexProperty` +|========================================================= + +*Arguments:* + +* `value` - One or more values to match against. +* `predicate` - A `P` predicate for value comparison. The predicate value may contain a `Traversal`. +* `traversal` - A child traversal whose first result is used as the value (implicitly wrapped in `P.eq()`). + Must be read-only. + +*Modulation:* + +None + +*Considerations:* + +* Equivalent to `has(T.value, ...)`. +* Operates on `Property` or `VertexProperty` traversers (typically reached via `properties()`). +* Child traversals must be read-only; mutating steps are rejected with an `Argument Error`. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[reference] + [[length-step]] === length() @@ -1808,6 +2045,44 @@ types which means that non-iterable types (including null) will cause exceptions See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java[source], link:https://tinkerpop.apache.org/docs/x.y.z/reference/#intersect-step[reference] +[[is-step]] +=== is() + +*Description:* Filters scalar values by testing them against a predicate or value. + +*Syntax:* `is(value: any)` | `is(predicate: P)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |N |`any` |`any` +|========================================================= + +*Arguments:* + +* `value` - A literal value or a `Traversal` to test equality against. `value` is implicitly wrapped + in `P.eq(value)`. +* `predicate` - A `P` predicate for comparison. The predicate value may be a literal or a `Traversal`. + +*Modulation:* + +None + +*Considerations:* + +* When a `Traversal` is supplied as a value or inside a `P`, it is resolved per-traverser: the current traverser seeds + the child traversal and its first result is used for comparison. +* If the child traversal produces no result, the comparison is aborted and the traverser is filtered out. +* Child traversals must be read-only; mutating steps are rejected with an `Argument Error`. +* Type mismatches during comparison (e.g., comparing a number to a string) result in the traverser being filtered. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#is-step[reference] + [[conjoin-step]] === conjoin() @@ -2217,6 +2492,53 @@ from the resulting `MAP`. See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java[source], link:https://tinkerpop.apache.org/docs/x.y.z/reference/#project-step[reference] +[[property-step]] +=== property() + +*Description:* Adds or sets properties on elements. This is a sideEffect step: it returns the element, not the +property it created. + +*Syntax:* `property(key: any, value: any, keyValues: any...)` | `property(cardinality: Cardinality, key: any, value: any, keyValues: any...)` | `property(keyValues: MAP)` | `property(cardinality: Cardinality, keyValues: MAP)` | `property(mapTraversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |N |`Element` |`Element` +|========================================================= + +*Arguments:* + +* `key` - The property key. May be a literal or a `Traversal` whose first result is used as the key. +* `value` - The property value. May be a literal or a `Traversal` whose first result is used as the value. +* `keyValues` - Additional key/value pairs for meta-properties on vertex properties. +* `cardinality` - The vertex property cardinality (`single`, `list`, `set`). If `null`, uses the graph's default. +* `keyValues` (`MAP`) - A map of property key-value pairs to set. Values may use `CardinalityValue` to override + the cardinality on a per-entry basis. +* `mapTraversal` - A child traversal that must produce a `MAP`. Each entry becomes a property on the element. + Must be read-only. + +*Modulation:* + +None + +*Considerations:* + +* When following `addV()` or `addE()`, the step may be folded into the creation operation (only when cardinality is + not specified and meta-properties are not included). +* Key and value arguments may be traversals; their first result is used per-traverser. +* A `MAP` argument (literal or from a traversal) sets multiple properties in one step. +* `property(null)` and `property(Cardinality, null)` are no-ops that return the input unchanged. +* Child traversals must be read-only; mutating steps are rejected with an `Argument Error`. +* If a map traversal does not produce a `MAP`, a `State Error` is raised. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. +* A `State Error` is raised if a map traversal does not produce a `MAP`. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#property-step[reference] + [[repeat-step]] === repeat() @@ -2659,6 +2981,45 @@ See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/j link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimLocalStep.java[source (local)], link:https://tinkerpop.apache.org/docs/x.y.z/reference/#trim-step[reference] +[[v-step]] +=== V() + +*Description:* Reads vertices from the graph by their identifiers. Can be used as a start step or mid-traversal. + +*Syntax:* `V(vertexIds: any...)` | `V(idTraversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|Y |Y |N |`any` |`Vertex` +|========================================================= + +*Arguments:* + +* `vertexIds` - Zero or more vertex identifiers. If none are provided, all vertices are returned. Arrays and + list-valued arguments are flattened (unrolled) into individual IDs. +* `idTraversal` - A child traversal which supplies vertex identifiers. The child traversal must be read-only + (no mutating steps). + +*Modulation:* + +None + +*Considerations:* + +* When used as a start step with a traversal argument, a synthetic traverser seeds the child traversal. +* When used mid-traversal with a traversal argument, the current traverser seeds the child traversal. +* If no vertices match the provided identifiers, the step produces no results. +* Graph providers may optimize `V()` with subsequent `has()` filters by folding `HasContainer` predicates into the + step for index-backed lookups. + +*Exceptions:* + +None + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java[source], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#graph-step[reference] + [[valueMap-step]] === valueMap() @@ -2707,3 +3068,49 @@ raised. See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java[source], link:https://tinkerpop.apache.org/docs/x.y.z/reference/#valuemap-step[reference], link:https://tinkerpop.apache.org/docs/x.y.z/reference/#propertymap-step[reference] + +[[where-step]] +=== where() + +*Description:* Filters traversers based on a predicate, a traversal, or a comparison between labeled steps. + +*Syntax:* `where(predicate: P)` | `where(startKey: STRING, predicate: P)` | `where(whereTraversal: Traversal)` + +[width="100%",options="header"] +|========================================================= +|Start Step |Mid Step |Modulated |Domain |Range +|N |Y |`by()` |`any` |`any` +|========================================================= + +*Arguments:* + +* `predicate` - A `P` predicate. The predicate value may reference a labeled step (scope key) or contain a `Traversal` + whose first result is used as the comparison value. +* `startKey` - A label identifying the traverser to use as the subject of the comparison. +* `whereTraversal` - A filtering traversal; traversers pass if the traversal produces at least one result. + +*Modulation:* + +* `by()` - Extracts comparison values. The first `by()` applies to the subject (current traverser or `startKey`), + the second applies to the predicate target. If a `by()` modulator is non-productive (produces no value), the + traverser is filtered out. + +*Considerations:* + +* `where(P)` with a scope-label value compares the current traverser (or labeled traverser) against the labeled value. +* `where(P)` with a traversal value resolves the child traversal per-traverser and compares directly against the + current value. +* `where(P)` can combine scope-label and traversal values in a `ConnectiveP` + (e.g., `P.neq('a').and(P.gt(traversal))`). +* `where(Traversal)` is an existence filter: traversers pass if the child traversal produces at least one result. +* Child traversals inside predicates must be read-only; mutating steps are rejected with an `Argument Error`. +* In OLAP, the anonymous traversal of `where()` processes the current object "locally" within the vertex's +star graph. It cannot traverse to adjacent vertices' properties or edges. + +*Exceptions:* + +* An `Argument Error` is raised if a child traversal contains mutating steps. + +See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java[source], +link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java[source (traversal)], +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#where-step[reference] diff --git a/docs/src/recipes/anti-patterns.asciidoc b/docs/src/recipes/anti-patterns.asciidoc index 18dde78dd61..d43b0917ed0 100644 --- a/docs/src/recipes/anti-patterns.asciidoc +++ b/docs/src/recipes/anti-patterns.asciidoc @@ -266,60 +266,3 @@ g.V().choose(label). <1> Note, that tokens use a `fold()` reducer by default. <2> `by("name")` doesn't use a token, but falls into the same category as the String `"name"` is translated into an optimized traversal. -[has-traversal] -== has() and Traversal Arguments - -There is an understandable assumption that the `has(String,Traversal)` overload indicates that the value returned by -the `Traversal` argument will be used as the comparative value for the specified property key. There are often similar -assumptions that values of `P` can take a `Traversal` argument to achieve a similar end as in -`has(String, eq(Traversal))`. Unfortunately, neither of these work as assumed. - -Starting with the latter issue of `P` and `Traversal` it should be noted that while `P` values take `Object` and thus -a `Traversal` it does not mean the `Traversal` will be resolved to a result that will be comparable. `P` will rather -do a compare on the raw `Traversal` object which of course will always return `false` (unless for some odd reason you -happen to store that `Traversal` object in your graph): - -[gremlin-groovy,modern] ----- -g.V().has('name', eq(constant('josh'))) -eq(constant('josh')) ----- - -As for the former issue with `has(String,Traversal)`, this requires a bit more explanation. The `Traversal` object is -meant to be treated as a `Predicate`, meaning that if it returns a value the `has()` will allow the traverser to pass: - -[gremlin-groovy,modern] ----- -g.V().has('name', constant('josh')) <1> -g.V().has('name', constant('josh').is('xyz')) <2> ----- - -<1> `constant()` always returns a value so all vertices pass through the `has()` -<2> By adding `is()` this `Traversal` will no longer return a value so no vertices pass through the `has()` - -These examples are a bit contrived for sake of demonstration, but the common pattern folks attempt appears as follows: - -[gremlin-groovy,modern] ----- -g.withSideEffect('x',['name': 'josh']).V().has('name', select('x').select('name')) ----- - -The above example represents a commonly seen mistake where we try to dynamically inject the value "josh" from a -`Map` stored in a side-effect named "x". As we can see, since `select('x').select('name')` returns a value the `has()` -succeeds for every single vertex which is unexpected. The correct way to do this dynamic injection is with `where()` -as in the following example: - -[gremlin-groovy,modern] ----- -g.withSideEffect('x',['name': 'josh']).V().as('a').where('a',eq('x')).by('name') ----- - -As a final note on this topic, it's worth noting how `has(String,Traversal)` can be used. Note that the traverser that -starts the `Traversal` argument is the `Property` value being compared. Therefore, if we wanted to find all the -vertices that had the "name" of "josh" we would do: - -[gremlin-groovy,modern] ----- -g.V().has('name', is('josh')) ----- - diff --git a/docs/src/recipes/traversal-induced-values.asciidoc b/docs/src/recipes/traversal-induced-values.asciidoc index 2d058a5ee22..ade12ed3a1d 100644 --- a/docs/src/recipes/traversal-induced-values.asciidoc +++ b/docs/src/recipes/traversal-induced-values.asciidoc @@ -30,33 +30,30 @@ g.V().has('name','marko').out('knows').has('age', gt(29)).values('name') In plain language, the above Gremlin asks, "What are the names of the people who Marko knows who are over the age of 29?". In this case, "29" is known as a constant to the traversal. Of course, if the question is changed slightly to instead ask, "What are the names of the people who Marko knows who are older than he is?", the hardcoding of "29" will -no longer suffice. There are multiple ways Gremlin would allow this second question to be answered. The first is -obvious to any programmer - use a variable: +no longer suffice. Rather than computing Marko's age in a separate query and passing it in as a variable, the value +can be _induced_ from the traversal itself by supplying a child `Traversal` to the predicate. The child traversal is +resolved for each traverser and its first result is used as the comparison value, so Marko's age is queried once and +then applied to filter the people he knows: [gremlin-groovy,modern] ---- -vMarko = g.V().has('name','marko').next() -g.V(vMarko).out('knows').has('age', gt(marko.value('age'))).values('name') ----- - -The downside to this approach is that it takes two separate traversals to answer the question. Ideally, there should -be a single traversal, that can query "marko" once, determine his `age` and then use that for the value supplied to -filter the people he knows. In this way the _value_ for the `age` in the `has()`-filter is _induced_ from the `Traversal` -itself. - -[gremlin-groovy,modern] ----- -g.V().has('name','marko').as('marko'). <1> - out('knows').as('friend'). <2> - where('friend', gt('marko')).by('age'). <3> - values('name') <4> +g.V().has('name','marko').as('marko'). <1> + out('knows'). <2> + has('age', gt(__.select('marko').values('age'))). <3> + values('name') <4> ---- <1> Find the "marko" `Vertex` and label it as "marko". -<2> Traverse out on the "knows" edges to the adjacent `Vertex` and label it as "friend". -<3> Continue to traverser only if Marko's current friend is older than him. +<2> Traverse out on the "knows" edges to Marko's friends. +<3> Keep a friend only if their `age` is greater than Marko's. The child traversal `__.select('marko').values('age')` +resolves Marko's age from the labelled "marko" vertex and `gt()` compares each friend's `age` against it. <4> Get the name of Marko's older friend. +The child traversal supplied to a predicate must be read-only; mutating steps such as `addV()` or `property()` are +rejected. See the link:https://tinkerpop.apache.org/docs/x.y.z/reference/#a-note-on-predicates[A Note on Predicates] +and link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[has()] sections of the reference documentation +for more detail on traversal-bearing predicates. + As another example of how traversal induced values can be used, consider a scenario where there was a graph that contained people, their friendship relationships, and the movies that they liked. diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc index b3116328ac4..5db65c45dbf 100644 --- a/docs/src/reference/the-traversal.asciidoc +++ b/docs/src/reference/the-traversal.asciidoc @@ -1311,6 +1311,9 @@ IMPORTANT: It is important to think of `choose()` as a branching step and not a intuitively lead to thinking the latter, where no match would mean to remove the traverser from the stream. As shown in the examples, this is not what happens. +NOTE: The `choose(P)` form and `choose().option(P, ...)` currently do not support traversal-bearing predicates. +Dynamic branching is restricted in 4.0.0. + The `choose()`-step can be used within a `map()` step to apply the branching logic to each element in a collection. [gremlin-groovy,modern] @@ -1794,15 +1797,18 @@ be used mid-traversal. ---- g.E(11) <1> g.E().hasLabel('knows').has('weight', gt(0.75)) -g.inject(1).coalesce(E().hasLabel("knows"), addE("knows").from(V().has("name","josh")).to(V().has("name","vadas"))) <2> +g.inject([7,8,9]).as('ids').E(__.select('ids').unfold()) <2> +g.inject(1).coalesce(E().hasLabel("knows"), addE("knows").from(V().has("name","josh")).to(V().has("name","vadas"))) <3> ---- <1> Find the edge by its unique identifier (i.e. `T.id`) - not all graphs will use a numeric value for their identifier. -<2> Get edges with label `knows`, if there is none then add new one between `josh` and `vadas`. +<2> Inject a list of edge IDs and use a child traversal with `select()` to dynamically resolve them for lookup. +<3> Get edges with label `knows`, if there is none then add new one between `josh` and `vadas`. *Additional References* -link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#E(java.lang.Object...)++[`E(Object...)`] +link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#E(java.lang.Object...)++[`E(Object...)`], +link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#E(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`E(Traversal)`] [[element-step]] === Element Step @@ -2145,6 +2151,10 @@ It is possible to filter vertices, edges, and vertex properties based on their p * `has(key,value)`: Remove the traverser if its element does not have the provided key/value property. * `has(label, key, value)`: Remove the traverser if its element does not have the specified label and provided key/value property. * `has(key,predicate)`: Remove the traverser if its element does not have a key value that satisfies the bi-predicate. For more information on predicates, please read <>. + * `has(key, traversal)`: Remove the traverser if its element's key value does not equal the first result of the provided traversal. + * `has(T, traversal)`: Remove the traverser if its element's `T`-based value (e.g. `T.id`, `T.label`) does not equal the first result of the provided traversal. + * `has(label, key, traversal)`: Remove the traverser if its element does not have the specified label and its key value does not equal the first result of the provided traversal. + * `hasLabel(traversal)`: Remove the traverser if its element's label does not equal the first result of the provided traversal. * `hasLabel(labels...)`: Remove the traverser if its element does not have any of the labels. * `hasId(ids...)`: Remove the traverser if its element does not have any of the ids. * `hasKey(keys...)`: Remove the `Property` traverser if it does not match one of the provided keys. @@ -2169,6 +2179,10 @@ g.V().hasNot('age').values('name') <7> g.V().has('person','name', startingWith('m')) <8> g.V().has(null, 'vadas') <9> g.V().has('person', 'name', regex('r')).values('name') <10> +g.V().has('age', P.gt(__.V(1).values('age'))) <11> +g.V().has('name', __.V(1).values('name')) <12> +g.V().hasLabel(__.V(1).label()) <13> +g.withSack(30).V().has('age', P.gt(__.sack())).values('name') <14> ---- <1> Find all vertices whose ages are between 20 (exclusive) and 30 (exclusive). In other words, the age must be greater than 20 and less than 30. @@ -2182,6 +2196,16 @@ the key,value pairs for those vertices. <8> Find all "person" vertices that have a name property that starts with the letter "m". <9> Property key is always stored as `String` and therefore an equality check with `null` will produce no result. <10> An example of using `has()` with regular expression predicate. +<11> Find all vertices whose age is greater than marko's age using a traversal for dynamic resolution. The child traversal +is evaluated per-traverser and its first result becomes the comparison value. +<12> Find all vertices whose name equals marko's name using a traversal as the value argument. +<13> Find all vertices whose label equals the label of vertex 1. +<14> Find all people older than a threshold carried in the traverser's `sack()` rather than read from the graph. + +NOTE: When a `Traversal` is provided directly as the value argument (not inside a `P`), it is internally wrapped in +`P.eq(traversal)`. Child traversals must be read-only. Mutating steps like `addV()` or `property()` are rejected with +an `IllegalArgumentException`. See <> for more details on traversal-bearing +predicates. *Additional References* @@ -2205,8 +2229,7 @@ link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#hasValue(org.apache.tinkerpop.gremlin.process.traversal.P)++[`hasValue(P)`], link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/P.html++[`P`], link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/TextP.html++[`TextP`], -link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/structure/T.html++[`T`], -link:++https://tinkerpop.apache.org/docs/x.y.z/recipes/#has-traversal++[Recipes - Anti-pattern] +link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/structure/T.html++[`T`] [[id-step]] === Id Step @@ -2528,15 +2551,23 @@ The term `is` is a reserved word in Python, and therefore must be referred to in g.V().values('age').is(32) g.V().values('age').is(lte(30)) g.V().values('age').is(inside(30, 40)) -g.V().where(__.in('created').count().is(1)).values('name') <1> -g.V().where(__.in('created').count().is(gte(2))).values('name') <2> +g.V().values('age').is(P.gt(__.V(1).values('age'))) <1> +g.V().hasLabel('person').values('age'). + is(P.gt(__.V().hasLabel('person').values('age').mean())) <2> +g.V().where(__.in('created').count().is(1)).values('name') <3> +g.V().where(__.in('created').count().is(gte(2))).values('name') <4> g.V().where(__.in('created').values('age'). - mean().is(inside(30d, 35d))).values('name') <3> + mean().is(inside(30d, 35d))).values('name') <5> ---- -<1> Find projects having exactly one contributor. -<2> Find projects having two or more contributors. -<3> Find projects whose contributors average age is between 30 and 35. +<1> Find all age values that are greater than marko's age using a traversal inside the predicate. +<2> Find all ages greater than the average person's age, where the threshold is computed dynamically by a child traversal. +<3> Find projects having exactly one contributor. +<4> Find projects having two or more contributors. +<5> Find projects whose contributors average age is between 30 and 35. + +NOTE: When `is(traversal)` is used directly (without an explicit predicate), it is internally wrapped in +`P.eq(traversal)`. *Additional References* @@ -4167,8 +4198,13 @@ g.V(1).property(list, ['age': single(36), 'city': 'wilmington', 'state': 'delawa g.V(1).valueMap() g.V(1).property('friendWeight',outE('knows').values('weight').sum(),'acl','private') <5> g.V(1).properties('friendWeight').valueMap() <6> -g.addV().property(T.label,'person').valueMap().with(WithOptions.tokens) <7> -g.addV().property(null) <8> +g.V(4).property( + __.V(1).project('friendCount', 'createdSoftware'). + by(__.out('knows').count()). + by(__.out('created').values('name'))) <7> +g.V(4).valueMap() +g.addV().property(T.label,'person').valueMap().with(WithOptions.tokens) <8> +g.addV().property(null) <9> g.addV().property(set, null) ---- @@ -4178,8 +4214,10 @@ g.addV().property(set, null) <4> Assign the `Cardinality` individually to override the specified `list` or the default cardinality if not specified. <5> It is possible to select the property value (as well as key) via a traversal. <6> For vertices, the `property()`-step can add meta-properties. -<7> The label value can be specified as a property only at the time a vertex is added and if one is not specified in the addV() -<8> If you pass a `null` value for the Map this will be treated as a no-op and the input will be returned +<7> A child traversal that produces a `Map` can set multiple properties at once. The child traversal cannot include +mutating steps (`IllegalArgumentException`) and must produce a `Map` (`IllegalStateException` otherwise). +<8> The label value can be specified as a property only at the time a vertex is added and if one is not specified in the addV() +<9> If you pass a `null` value for the Map this will be treated as a no-op and the input will be returned *Additional References* @@ -5366,12 +5404,14 @@ be used mid-traversal. [gremlin-groovy,modern] ---- g.V(1) <1> +g.inject([1,2,4]).as('ids').V(__.select('ids').unfold()).values('name') <2> g.V().has('name', within('marko', 'vadas', 'josh')).as('person'). - V().has('name', within('lop', 'ripple')).addE('uses').from('person') <2> + V().has('name', within('lop', 'ripple')).addE('uses').from('person') <3> ---- <1> Find the vertex by its unique identifier (i.e. `T.id`) - not all graphs will use a numeric value for their identifier. -<2> An example where `V()` is used both as a start step and in the middle of a traversal. +<2> Dynamically resolve the vertex lookup from a child traversal. +<3> An example where `V()` is used both as a start step and in the middle of a traversal. NOTE: Whether a mid-traversal `V()` uses an index or not, depends on a) whether suitable index exists and b) if the particular graph system provider implemented this functionality. @@ -5389,7 +5429,8 @@ g.V().has('name', within('marko', 'vadas', 'josh')).as('person'). *Additional References* -link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#V(java.lang.Object...)++[`V(Object...)`] +link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#V(java.lang.Object...)++[`V(Object...)`], +link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#V(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`V(Traversal)`] [[value-step]] === Value Step @@ -5587,6 +5628,8 @@ g.V().as('a').out('knows').as('b'). by('name') <8> g.V().as('a').both().both().as('b'). where('a',eq('b')).by('age') <9> +g.V().values('age').where(P.gt(__.V(1).values('age'))) <10> +g.V().where(P.gt(__.V(1).values('age'))).by('age').values('name') <11> ---- <1> What are the names of the people who have created a project? @@ -5598,6 +5641,8 @@ g.V().as('a').both().both().as('b'). <7> Marko knows josh and vadas but is only older than vadas. <8> Marko is younger than josh, but josh knows someone equal in age to marko (which is marko). <9> The "age" property is not <> for all vertices and therefore those values are filtered. +<10> Find all age values that are greater than marko's age, where marko's age is resolved dynamically via a child traversal. +<11> Find all people older than marko. The child traversal resolves marko's age, and `by('age')` extracts the age from each vertex for comparison. WARNING: The anonymous traversal of `where()` processes the current object "locally". In OLAP, where the atomic unit of computing is the vertex and its local "star graph," it is important that the anonymous traversal does not leave @@ -5724,6 +5769,28 @@ NOTE: The TinkerPop reference implementation uses the Java `Pattern` and `Matche engine. Other implementations may decide to use a different regular expression engine. It's a good idea to check the documentation for the implementation you are using to verify the allowed regular expression syntax. +In addition to literal values, most predicates also accept a `Traversal` argument. When a traversal is provided, it is +evaluated and only its first result is used for comparison, consistent with `by(traversal)` first-result semantics. +The child traversal must be read-only. Mutating steps are rejected. + +* For `within()` and `without()` with a single traversal, the first result mirrors the single-collection form + `within(Collection)`: if it is a `Collection` its elements form the membership set, otherwise it is treated as one + value. Use `fold()` in the child traversal to produce a collection. +* The multi-traversal form `within(trav1, trav2, ...)` mirrors the literal varargs form `within(v1, v2, ...)`: each + traversal contributes its first result as a single membership element (no unfolding). To build one flat set from + several sources, combine them in a single child traversal with `union(...).fold()`. + +[gremlin-groovy,modern] +---- +g.V().has('age', P.gt(__.V(1).values('age'))) <1> +g.V().has('age', P.within(__.V(1).out('knows').values('age').fold())) <2> +g.V().has('name', P.within(__.union(__.V(1).out('knows').values('name'), __.constant('peter')).fold())) <3> +---- + +<1> Find vertices whose age is greater than marko's age using a traversal inside the predicate. +<2> Find vertices whose age is in the set of ages of marko's friends, using `fold()` to produce a collection. +<3> Combine multiple sources into one membership set with `union(...).fold()`. + [gremlin-groovy] ---- eq(2) diff --git a/docs/src/upgrade/release-4.x.x.asciidoc b/docs/src/upgrade/release-4.x.x.asciidoc index 0c1a3ca37d4..a6040deba56 100644 --- a/docs/src/upgrade/release-4.x.x.asciidoc +++ b/docs/src/upgrade/release-4.x.x.asciidoc @@ -403,6 +403,63 @@ partial work is discarded if the user forgets to call `commit()`. In Java (both can still be overridden via `tx.onClose(Transaction.CLOSE_BEHAVIOR.COMMIT)`. The non-Java GLVs do not support configuring close behavior and always rollback. +==== Expanding Dynamic Arguments to Additional Steps + +Prior to 4.0, comparing a traverser's value against a dynamically computed reference required several coordinated +step labels and `where()` comparison. For example, finding all people older than "marko" previously required: + +[source,groovy] +---- +// Old way: label marko's age, compare via where() +gremlin> g.V(1).values("age").as("markosAge"). +......1> V().hasLabel("person").as("p"). +......2> values("age").as("otherAge"). +......3> where("otherAge", gt("markosAge")). +......4> select("p").values("name") +==>josh +==>peter +---- + +This pattern required several coordinated step labels and could not easily compose with other predicates. With +traversal-accepting arguments, the same query becomes a single, readable step: + +[source,groovy] +---- +// New way: traversal inside the predicate +gremlin> g.V().has("age", P.gt(__.V(1).values("age"))).values("name") +==>josh +==>peter +---- + +Steps and predicates that previously only accepted literal values now accept child traversals resolved per-traverser +at runtime. Affected steps: `has()`, `hasId()`, `hasKey()`, `hasLabel()`, `hasValue()`, `V()`, `E()`, `property()`, +`is()`, `where(P)`, and all `P` and `TextP` predicates. + +[source,groovy] +---- +// Multi-source filtering with within() - combine sources in one traversal with union().fold() +gremlin> g.V().has("name", P.within(__.union(__.V(1).out("knows").values("name"), __.constant("peter")).fold())) +==>v[2] +==>v[4] +==>v[6] + +// Set multiple properties from a computed Map +gremlin> g.V(4).property(__.V(1).project("friendCount").by(__.out("knows").count())) +==>v[4] +---- + +Users should look to simplify existing traversals that use `as()`/`where()`/`select()` patterns solely to compare +a traverser against a dynamically computed value. In particular, patterns of the form +`__.as("x")...where("x", P.gt("y"))` can often be replaced with a single `has()` or `is()` step containing +a traversal predicate. + +See: <>, <>, <>, <>, +<>, +link:https://issues.apache.org/jira/browse/TINKERPOP-2586[TINKERPOP-2586], +link:https://issues.apache.org/jira/browse/TINKERPOP-2777[TINKERPOP-2777], +link:https://issues.apache.org/jira/browse/TINKERPOP-3005[TINKERPOP-3005], +link:https://issues.apache.org/jira/browse/TINKERPOP-1463[TINKERPOP-1463] + ==== Removed `uuid` Dependency in gremlin-javascript The `uuid` npm package has been removed from `gremlin-javascript`. UUID generation now uses the built-in @@ -952,6 +1009,21 @@ serializer. As a result, Gryo-serialized `Tree` data written by 3.x cannot be re Gryo type registration id (`61`) is unchanged and 4.x-to-4.x Gryo round-trips correctly; this Gryo break is expected for the 4.0.0 major release. +===== Traversal-Accepting Steps - HasContainer Guard + +Steps and predicates now accept child traversals resolved at runtime. `HasContainer` instances that hold a child +traversal cannot be folded into index lookups because their value is dynamic (resolved per-traverser). Providers that +fold `HasContainer` predicates into their graph step must guard against this: + +[source,java] +---- +if (hasContainer.hasTraversal()) continue; // skip - dynamic value, cannot fold into index +---- + +`GraphStep.processHasContainerIds()` already includes this guard. Providers that implement their own `HasContainer` +folding strategy should add the same check. Without it, the container's value is read before it has been resolved +against a traverser, so an unresolved value would be folded into the index lookup and produce incorrect results. + ==== Graph Driver Providers ===== Request Interceptors diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java index 0431a36f056..8a842abb97e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java @@ -455,6 +455,18 @@ protected void notImplemented(final ParseTree ctx) { * {@inheritDoc} */ @Override public T visitTraversalMethod_has_T_P(final GremlinParser.TraversalMethod_has_T_PContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_has_String_Traversal(final GremlinParser.TraversalMethod_has_String_TraversalContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_has_T_Traversal(final GremlinParser.TraversalMethod_has_T_TraversalContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_has_String_String_Traversal(final GremlinParser.TraversalMethod_has_String_String_TraversalContext ctx) { notImplemented(ctx); return null; } /** * {@inheritDoc} */ @@ -471,10 +483,15 @@ protected void notImplemented(final ParseTree ctx) { * {@inheritDoc} */ @Override public T visitTraversalMethod_hasKey_String_String(final GremlinParser.TraversalMethod_hasKey_String_StringContext ctx) { notImplemented(ctx); return null; } + @Override public T visitTraversalMethod_hasKey_Traversal(final GremlinParser.TraversalMethod_hasKey_TraversalContext ctx) { notImplemented(ctx); return null; } /** * {@inheritDoc} */ @Override public T visitTraversalMethod_hasLabel_P(final GremlinParser.TraversalMethod_hasLabel_PContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_hasLabel_Traversal(final GremlinParser.TraversalMethod_hasLabel_TraversalContext ctx) { notImplemented(ctx); return null; } /** * {@inheritDoc} */ @@ -491,6 +508,7 @@ protected void notImplemented(final ParseTree ctx) { * {@inheritDoc} */ @Override public T visitTraversalMethod_hasValue_P(final GremlinParser.TraversalMethod_hasValue_PContext ctx) { notImplemented(ctx); return null; } + @Override public T visitTraversalMethod_hasValue_Traversal(final GremlinParser.TraversalMethod_hasValue_TraversalContext ctx) { notImplemented(ctx); return null; } /** * {@inheritDoc} */ @@ -711,6 +729,18 @@ protected void notImplemented(final ParseTree ctx) { * {@inheritDoc} */ @Override public T visitTraversalMethod_property_Object(final GremlinParser.TraversalMethod_property_ObjectContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_property_Cardinality_Object_Traversal(final GremlinParser.TraversalMethod_property_Cardinality_Object_TraversalContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_property_Object_Traversal(final GremlinParser.TraversalMethod_property_Object_TraversalContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_property_Traversal(final GremlinParser.TraversalMethod_property_TraversalContext ctx) { notImplemented(ctx); return null; } /** * {@inheritDoc} */ 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 2c4980224a8..fe0d4220921 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 @@ -22,15 +22,23 @@ import org.apache.tinkerpop.gremlin.process.traversal.Merge; import org.apache.tinkerpop.gremlin.process.traversal.Operator; import org.apache.tinkerpop.gremlin.process.traversal.Order; +import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Pop; import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions; import org.apache.tinkerpop.gremlin.process.traversal.Scope; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepPlaceholder; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer; +import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper; import org.apache.tinkerpop.gremlin.structure.Column; import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality; import java.util.Arrays; @@ -65,7 +73,14 @@ public Traversal visitTraversalMethod(final GremlinParser.TraversalMethodContext */ @Override public GraphTraversal visitTraversalMethod_V(final GremlinParser.TraversalMethod_VContext ctx) { - return this.graphTraversal.V(antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs())); + if (ctx.nestedTraversal() != null) { + return this.graphTraversal.V((Traversal) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + final Object[] args = antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs()); + if (args.length == 1 && args[0] instanceof Traversal) { + return this.graphTraversal.V((Traversal) args[0]); + } + return this.graphTraversal.V(args); } /** @@ -73,7 +88,14 @@ public GraphTraversal visitTraversalMethod_V(final GremlinParser.TraversalMethod */ @Override public GraphTraversal visitTraversalMethod_E(final GremlinParser.TraversalMethod_EContext ctx) { - return this.graphTraversal.E(antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs())); + if (ctx.nestedTraversal() != null) { + return this.graphTraversal.E((Traversal) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + final Object[] args = antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs()); + if (args.length == 1 && args[0] instanceof Traversal) { + return this.graphTraversal.E((Traversal) args[0]); + } + return this.graphTraversal.E(args); } /** @@ -741,6 +763,15 @@ public GraphTraversal visitTraversalMethod_hasKey_String_String(final GremlinPar } } + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_hasKey_Traversal(final GremlinParser.TraversalMethod_hasKey_TraversalContext ctx) { + final Traversal.Admin traversal = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()); + return graphTraversal.hasKey((Traversal) traversal); + } + /** * {@inheritDoc} */ @@ -749,6 +780,15 @@ public GraphTraversal visitTraversalMethod_hasLabel_P(final GremlinParser.Traver return graphTraversal.hasLabel(antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate())); } + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_hasLabel_Traversal(final GremlinParser.TraversalMethod_hasLabel_TraversalContext ctx) { + final Traversal.Admin traversal = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()); + return graphTraversal.hasLabel((Traversal) traversal); + } + /** * {@inheritDoc} */ @@ -807,6 +847,15 @@ public GraphTraversal visitTraversalMethod_hasValue_P(final GremlinParser.Traver return graphTraversal.hasValue(antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate())); } + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_hasValue_Traversal(final GremlinParser.TraversalMethod_hasValue_TraversalContext ctx) { + final Traversal.Admin traversal = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()); + return graphTraversal.hasValue((Traversal) traversal); + } + /** * {@inheritDoc} */ @@ -820,8 +869,12 @@ public GraphTraversal visitTraversalMethod_has_String(final GremlinParser.Traver */ @Override public GraphTraversal visitTraversalMethod_has_String_Object(final GremlinParser.TraversalMethod_has_String_ObjectContext ctx) { - return graphTraversal.has(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()), - antlr.argumentVisitor.visitGenericArgument(ctx.genericArgument())); + final String key = antlr.genericVisitor.parseString(ctx.stringNullableLiteral()); + final Object value = antlr.argumentVisitor.visitGenericArgument(ctx.genericArgument()); + if (value instanceof Traversal) { + return graphTraversal.has(key, (Traversal) value); + } + return graphTraversal.has(key, value); } /** @@ -839,14 +892,19 @@ public GraphTraversal visitTraversalMethod_has_String_P(final GremlinParser.Trav @Override public GraphTraversal visitTraversalMethod_has_String_String_Object(final GremlinParser.TraversalMethod_has_String_String_ObjectContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument()); + final String key = antlr.genericVisitor.parseString(ctx.stringNullableLiteral()); + final Object value = antlr.argumentVisitor.visitGenericArgument(ctx.genericArgument()); + if (value instanceof Traversal) { + if (GValue.valueInstanceOf(literalOrVar, String.class)) { + return graphTraversal.has(((GValue) literalOrVar).get(), key, (Traversal) value); + } else { + return graphTraversal.has((String) literalOrVar, key, (Traversal) value); + } + } if (GValue.valueInstanceOf(literalOrVar, String.class)) { - return graphTraversal.has((GValue) literalOrVar, - antlr.genericVisitor.parseString(ctx.stringNullableLiteral()), - antlr.argumentVisitor.visitGenericArgument(ctx.genericArgument())); + return graphTraversal.has((GValue) literalOrVar, key, value); } else { - return graphTraversal.has((String) literalOrVar, - antlr.genericVisitor.parseString(ctx.stringNullableLiteral()), - antlr.argumentVisitor.visitGenericArgument(ctx.genericArgument())); + return graphTraversal.has((String) literalOrVar, key, value); } } @@ -872,8 +930,12 @@ public GraphTraversal visitTraversalMethod_has_String_String_P(final GremlinPars */ @Override public GraphTraversal visitTraversalMethod_has_T_Object(final GremlinParser.TraversalMethod_has_T_ObjectContext ctx) { - return graphTraversal.has(TraversalEnumParser.parseTraversalEnumFromContext(T.class, ctx.traversalT()), - antlr.argumentVisitor.visitGenericArgument(ctx.genericArgument())); + final T accessor = TraversalEnumParser.parseTraversalEnumFromContext(T.class, ctx.traversalT()); + final Object value = antlr.argumentVisitor.visitGenericArgument(ctx.genericArgument()); + if (value instanceof Traversal) { + return graphTraversal.has(accessor, (Traversal) value); + } + return graphTraversal.has(accessor, value); } /** @@ -885,6 +947,41 @@ public GraphTraversal visitTraversalMethod_has_T_P(final GremlinParser.Traversal antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate())); } + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_has_String_Traversal(final GremlinParser.TraversalMethod_has_String_TraversalContext ctx) { + final String key = antlr.genericVisitor.parseString(ctx.stringNullableLiteral()); + final Traversal.Admin traversal = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()); + return this.graphTraversal.has(key, (Traversal) traversal); + } + + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_has_String_String_Traversal(final GremlinParser.TraversalMethod_has_String_String_TraversalContext ctx) { + final Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument()); + final String key = antlr.genericVisitor.parseString(ctx.stringNullableLiteral()); + final Traversal.Admin traversal = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()); + if (GValue.valueInstanceOf(literalOrVar, String.class)) { + return this.graphTraversal.has(((GValue) literalOrVar).get(), key, (Traversal) traversal); + } else { + return this.graphTraversal.has((String) literalOrVar, key, (Traversal) traversal); + } + } + + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_has_T_Traversal(final GremlinParser.TraversalMethod_has_T_TraversalContext ctx) { + final T accessor = TraversalEnumParser.parseTraversalEnumFromContext(T.class, ctx.traversalT()); + final Traversal.Admin traversal = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()); + return this.graphTraversal.has(accessor, (Traversal) traversal); + } + /** * {@inheritDoc} */ @@ -1449,6 +1546,36 @@ public Traversal visitTraversalMethod_property_Object(final GremlinParser.Traver return graphTraversal.property(antlr.argumentVisitor.parseMap(ctx.genericMapNullableArgument())); } + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_property_Cardinality_Object_Traversal(final GremlinParser.TraversalMethod_property_Cardinality_Object_TraversalContext ctx) { + return graphTraversal.property( + TraversalEnumParser.parseTraversalEnumFromContext(Cardinality.class, ctx.traversalCardinality()), + antlr.genericVisitor.visitGenericLiteral(ctx.genericLiteral()), + antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_property_Object_Traversal(final GremlinParser.TraversalMethod_property_Object_TraversalContext ctx) { + return graphTraversal.property( + antlr.genericVisitor.visitGenericLiteral(ctx.genericLiteral()), + antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_property_Traversal(final GremlinParser.TraversalMethod_property_TraversalContext ctx) { + final Traversal traversal = (Traversal) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()); + return this.graphTraversal.property(traversal); + } + /** * {@inheritDoc} */ diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java index 19a5ab4f29c..c504c2e76d9 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java @@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.GType; import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.TextP; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import java.util.Collection; @@ -67,6 +68,9 @@ public P visitTraversalPredicate(final GremlinParser.TraversalPredicateContext c */ @Override public P visitTraversalPredicate_eq(final GremlinParser.TraversalPredicate_eqContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.eq((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return P.eq(getSingleGenericLiteralArgument(ctx)); } @@ -75,6 +79,9 @@ public P visitTraversalPredicate_eq(final GremlinParser.TraversalPredicate_eqCon */ @Override public P visitTraversalPredicate_neq(final GremlinParser.TraversalPredicate_neqContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.neq((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return P.neq(getSingleGenericLiteralArgument(ctx)); } @@ -97,6 +104,9 @@ public P visitTraversalPredicate_typeOf(final GremlinParser.TraversalPredicate_t */ @Override public P visitTraversalPredicate_lt(final GremlinParser.TraversalPredicate_ltContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.lt((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return P.lt(getSingleGenericLiteralArgument(ctx)); } @@ -105,6 +115,9 @@ public P visitTraversalPredicate_lt(final GremlinParser.TraversalPredicate_ltCon */ @Override public P visitTraversalPredicate_lte(final GremlinParser.TraversalPredicate_lteContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.lte((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return P.lte(getSingleGenericLiteralArgument(ctx)); } @@ -113,6 +126,9 @@ public P visitTraversalPredicate_lte(final GremlinParser.TraversalPredicate_lteC */ @Override public P visitTraversalPredicate_gt(final GremlinParser.TraversalPredicate_gtContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.gt((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return P.gt(getSingleGenericLiteralArgument(ctx)); } @@ -121,6 +137,9 @@ public P visitTraversalPredicate_gt(final GremlinParser.TraversalPredicate_gtCon */ @Override public P visitTraversalPredicate_gte(final GremlinParser.TraversalPredicate_gteContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.gte((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return P.gte(getSingleGenericLiteralArgument(ctx)); } @@ -129,6 +148,11 @@ public P visitTraversalPredicate_gte(final GremlinParser.TraversalPredicate_gteC */ @Override public P visitTraversalPredicate_inside(final GremlinParser.TraversalPredicate_insideContext ctx) { + if (!ctx.nestedTraversal().isEmpty()) { + final Traversal.Admin first = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal(0)); + final Traversal.Admin second = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal(1)); + return P.gt(first).and(P.lt(second)); + } final Object[] arguments = getDoubleGenericLiteralArgument(ctx); return P.inside(arguments[0], arguments[1]); } @@ -138,6 +162,11 @@ public P visitTraversalPredicate_inside(final GremlinParser.TraversalPredicate_i */ @Override public P visitTraversalPredicate_outside(final GremlinParser.TraversalPredicate_outsideContext ctx) { + if (!ctx.nestedTraversal().isEmpty()) { + final Traversal.Admin first = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal(0)); + final Traversal.Admin second = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal(1)); + return P.lt(first).or(P.gt(second)); + } final Object[] arguments = getDoubleGenericLiteralArgument(ctx); return P.outside(arguments[0], arguments[1]); } @@ -147,6 +176,11 @@ public P visitTraversalPredicate_outside(final GremlinParser.TraversalPredicate_ */ @Override public P visitTraversalPredicate_between(final GremlinParser.TraversalPredicate_betweenContext ctx) { + if (!ctx.nestedTraversal().isEmpty()) { + final Traversal.Admin first = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal(0)); + final Traversal.Admin second = (Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal(1)); + return P.gte(first).and(P.lt(second)); + } final Object[] arguments = getDoubleGenericLiteralArgument(ctx); return P.between(arguments[0], arguments[1]); } @@ -156,6 +190,10 @@ public P visitTraversalPredicate_between(final GremlinParser.TraversalPredicate_ */ @Override public P visitTraversalPredicate_within(final GremlinParser.TraversalPredicate_withinContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.within((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + // called with no args which is valid for java/groovy if (null == ctx.genericArgumentVarargs()) return P.within(); @@ -175,6 +213,10 @@ public P visitTraversalPredicate_within(final GremlinParser.TraversalPredicate_w */ @Override public P visitTraversalPredicate_without(final GremlinParser.TraversalPredicate_withoutContext ctx) { + if (ctx.nestedTraversal() != null) { + return P.without((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + // called with no args which is valid for java/groovy if (null == ctx.genericArgumentVarargs()) return P.without(); @@ -199,31 +241,49 @@ public P visitTraversalPredicate_not(final GremlinParser.TraversalPredicate_notC @Override public P visitTraversalPredicate_containing(final GremlinParser.TraversalPredicate_containingContext ctx) { + if (ctx.nestedTraversal() != null) { + return TextP.containing((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return TextP.containing((String) antlr.argumentVisitor.visitStringArgument(ctx.stringArgument())); } @Override public P visitTraversalPredicate_notContaining(final GremlinParser.TraversalPredicate_notContainingContext ctx) { + if (ctx.nestedTraversal() != null) { + return TextP.notContaining((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return TextP.notContaining((String) antlr.argumentVisitor.visitStringArgument(ctx.stringArgument())); } @Override public P visitTraversalPredicate_notEndingWith(final GremlinParser.TraversalPredicate_notEndingWithContext ctx) { + if (ctx.nestedTraversal() != null) { + return TextP.notEndingWith((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return TextP.notEndingWith((String) antlr.argumentVisitor.visitStringArgument(ctx.stringArgument())); } @Override public P visitTraversalPredicate_endingWith(final GremlinParser.TraversalPredicate_endingWithContext ctx) { + if (ctx.nestedTraversal() != null) { + return TextP.endingWith((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return TextP.endingWith((String) antlr.argumentVisitor.visitStringArgument(ctx.stringArgument())); } @Override public P visitTraversalPredicate_startingWith(final GremlinParser.TraversalPredicate_startingWithContext ctx) { + if (ctx.nestedTraversal() != null) { + return TextP.startingWith((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return TextP.startingWith((String) antlr.argumentVisitor.visitStringArgument(ctx.stringArgument())); } @Override public P visitTraversalPredicate_notStartingWith(final GremlinParser.TraversalPredicate_notStartingWithContext ctx) { + if (ctx.nestedTraversal() != null) { + return TextP.notStartingWith((Traversal.Admin) antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); + } return TextP.notStartingWith((String) antlr.argumentVisitor.visitStringArgument(ctx.stringArgument())); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java index 1b70a58c8d1..bca22cb6d82 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java @@ -19,9 +19,14 @@ package org.apache.tinkerpop.gremlin.language.grammar; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; + import java.util.Map; /** @@ -94,7 +99,14 @@ public GraphTraversal visitTraversalSourceSpawnMethod_addV(final GremlinParser.T */ @Override public GraphTraversal visitTraversalSourceSpawnMethod_E(final GremlinParser.TraversalSourceSpawnMethod_EContext ctx) { - return this.traversalSource.E(antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs())); + if (ctx.nestedTraversal() != null) { + return this.traversalSource.E((Traversal) anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + final Object[] args = antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs()); + if (args.length == 1 && args[0] instanceof Traversal) { + return this.traversalSource.E((Traversal) args[0]); + } + return this.traversalSource.E(args); } /** @@ -102,7 +114,14 @@ public GraphTraversal visitTraversalSourceSpawnMethod_E(final GremlinParser.Trav */ @Override public GraphTraversal visitTraversalSourceSpawnMethod_V(final GremlinParser.TraversalSourceSpawnMethod_VContext ctx) { - return this.traversalSource.V(antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs())); + if (ctx.nestedTraversal() != null) { + return this.traversalSource.V((Traversal) anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal())); + } + final Object[] args = antlr.argumentVisitor.parseObjectVarargs(ctx.genericArgumentVarargs()); + if (args.length == 1 && args[0] instanceof Traversal) { + return this.traversalSource.V((Traversal) args[0]); + } + return this.traversalSource.V(args); } /** diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java index 37674711555..5011447af76 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java @@ -768,6 +768,16 @@ public Void visitTraversalMethod_hasLabel_P(final GremlinParser.TraversalMethod_ return null; } + @Override + public Void visitTraversalMethod_hasLabel_Traversal(final GremlinParser.TraversalMethod_hasLabel_TraversalContext ctx) { + final String step = ctx.getChild(0).getText(); + sb.append(convertToPascalCase(step)); + sb.append("("); + visit(ctx.nestedTraversal()); + sb.append(")"); + return null; + } + @Override public Void visitTraversalMethod_hasLabel_String_String(final GremlinParser.TraversalMethod_hasLabel_String_StringContext ctx) { // if there is only one argument then cast to string otherwise it's ambiguous with hasLabel(P) @@ -1008,6 +1018,49 @@ public Void visitTraversalMethod_properties(final GremlinParser.TraversalMethod_ return handleGenerics(ctx); } + @Override + public Void visitTraversalMethod_property_Object(final GremlinParser.TraversalMethod_property_ObjectContext ctx) { + // Property(null) is ambiguous with Property(ITraversal) - cast null to IDictionary to disambiguate + if (ctx.genericMapNullableArgument().genericMapNullableLiteral() != null && + ctx.genericMapNullableArgument().genericMapNullableLiteral().nullLiteral() != null) { + visit(ctx.getChild(0)); + sb.append("("); + sb.append("(IDictionary) "); + visit(ctx.genericMapNullableArgument()); + sb.append(")"); + return null; + } + return super.visitTraversalMethod_property_Object(ctx); + } + + @Override + public Void visitTraversalMethod_property_Cardinality_Object(final GremlinParser.TraversalMethod_property_Cardinality_ObjectContext ctx) { + // Property(Cardinality, null) - cast null to IDictionary to disambiguate + if (ctx.genericMapNullableArgument().genericMapNullableLiteral() != null && + ctx.genericMapNullableArgument().genericMapNullableLiteral().nullLiteral() != null) { + visit(ctx.getChild(0)); + sb.append("("); + visit(ctx.traversalCardinality()); + sb.append(", "); + sb.append("(IDictionary) "); + visit(ctx.genericMapNullableArgument()); + sb.append(")"); + return null; + } + return super.visitTraversalMethod_property_Cardinality_Object(ctx); + } + + @Override + public Void visitTraversalMethod_property_Traversal(final GremlinParser.TraversalMethod_property_TraversalContext ctx) { + // Property(ITraversal) - cast to ITraversal to disambiguate + visit(ctx.getChild(0)); + sb.append("("); + sb.append("(ITraversal) "); + visit(ctx.nestedTraversal()); + sb.append(")"); + return null; + } + @Override public Void visitTraversalMethod_property_Cardinality_Object_Object_Object(final GremlinParser.TraversalMethod_property_Cardinality_Object_Object_ObjectContext ctx) { if (ctx.genericArgumentVarargs() == null || ctx.genericArgumentVarargs().getChildCount() == 0) { diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java index 3bd1cb5287c..c974514aa72 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java @@ -317,7 +317,11 @@ private String asString(final P p) { final StringBuilder sb = new StringBuilder(); if (p instanceof TextP) { sb.append("TextP.").append(p.getPredicateName()).append("("); - sb.append(argAsString(p.getValue())); + if (p.hasTraversal()) { + sb.append(argAsString(p.getChildTraversals().get(0))); + } else { + sb.append(argAsString(p.getValue())); + } } else if (p instanceof ConnectiveP) { // ConnectiveP gets some special handling because it's reduced to and(P, P, P) and we want it // generated the way it was written which was P.and(P).and(P) @@ -337,6 +341,18 @@ private String asString(final P p) { } else if (p instanceof NotP) { sb.append("P.not("); sb.append(argAsString(p.negate())); // Wrap internal P in `P.not(%s)` + } else if (p.hasTraversal()) { + // Traversal-bearing predicate: serialize as P.op(traversalGremlinLang) + sb.append("P.").append(p.getPredicateName()).append("("); + final List> traversals = p.getChildTraversals(); + if (traversals.size() > 1) { + for (int i = 0; i < traversals.size(); i++) { + if (i > 0) sb.append(","); + sb.append(argAsString(traversals.get(i))); + } + } else { + sb.append(argAsString(traversals.get(0))); + } } else { sb.append("P.").append(p.getPredicateName()).append("("); sb.append(argAsString(p.getValue())); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/NotP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/NotP.java index f77f0f59742..aca1d241e40 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/NotP.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/NotP.java @@ -59,17 +59,41 @@ public String toString() { } /** - * Returns the original unwrapped P contained within this NotP, as double negation cancels out. + * Returns the inner predicate wrapped by this NotP. + */ + public P getWrapped() { + return this.originalP; + } + + /** + * Returns the original unwrapped P, since double negation cancels out. + * @apiNote Functionally identical to {@link #getWrapped()}, but fulfills the {@link java.util.function.Predicate#negate()} contract. */ @Override public P negate() { - return originalP; + return getWrapped(); } public P clone() { return new NotP<>(this.originalP.clone()); } + @Override + public boolean hasTraversal() { + return super.hasTraversal() || this.originalP.hasTraversal(); + } + + @Override + public boolean isResolvedEmpty() { + return this.originalP.isResolvedEmpty(); + } + + @Override + public void resolve(final Traverser.Admin traverser) { + super.resolve(traverser); + this.originalP.resolve(traverser); + } + /** * A NotPBiPredicate wraps a PBiPredicate and represents its negation. */ diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java index afc41b5681c..af958cf8bc3 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java @@ -19,10 +19,14 @@ package org.apache.tinkerpop.gremlin.process.traversal; import org.apache.commons.collections4.CollectionUtils; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet; import org.apache.tinkerpop.gremlin.process.traversal.util.AndP; +import org.apache.tinkerpop.gremlin.process.traversal.util.ReadOnlyChildValidator; +import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP; import org.apache.tinkerpop.gremlin.process.traversal.util.OrP; +import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator; import java.io.Serializable; import java.util.ArrayList; @@ -31,11 +35,11 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; -import java.util.Optional; +import java.util.Objects; import java.util.Set; import java.util.function.Predicate; -import java.util.stream.Collectors; /** * Predefined {@code Predicate} values that can be used to define filters to {@code has()} and {@code where()}. @@ -49,10 +53,12 @@ public class P implements Predicate, Serializable, Cloneable { protected Map variables = new HashMap<>(); protected Collection literals = Collections.EMPTY_LIST; private boolean isCollection = false; + private boolean resolvedEmpty = false; + private List> childTraversals; public P(final PBiPredicate biPredicate, final V value) { - setValue(value); this.biPredicate = biPredicate; + setValue(value); } public P(final PBiPredicate biPredicate, final GValue value) { @@ -81,6 +87,31 @@ protected P(final PBiPredicate biPredicate, final Collection literals, this.isCollection = isCollection; } + /** + * Constructs a {@code P} with a child traversal whose result is resolved at runtime against the current + * traverser. The literals and variables are left at their defaults and will be populated when + * {@link #resolve(Traverser.Admin)} is called. + */ + @SuppressWarnings("unchecked") + public P(final PBiPredicate biPredicate, final Traversal.Admin traversalValue) { + this.biPredicate = biPredicate; + setValue((V) traversalValue); + } + + /** + * Constructs a {@code P} with multiple child traversals resolved at runtime against the current traverser. + * Only valid for collection predicates ({@link Contains#within}, {@link Contains#without}). Each traversal + * contributes its first result only. The literals and variables are left at their defaults and will be + * populated when {@link #resolve(Traverser.Admin)} is called. + * + * @since 4.0.0 + */ + @SuppressWarnings("unchecked") + public P(final PBiPredicate biPredicate, final List> traversalValues) { + this.biPredicate = biPredicate; + setValue((V) traversalValues); + } + public PBiPredicate getBiPredicate() { return this.biPredicate; } @@ -116,21 +147,50 @@ public V getValue() { } public void setValue(final V value) { - variables.clear(); - literals = Collections.EMPTY_LIST; + // Full reset — completely replace the predicate's value state. + this.childTraversals = null; + this.variables.clear(); + this.literals = Collections.EMPTY_LIST; + this.isCollection = false; + this.resolvedEmpty = false; + applyValue(value); + } - if (value == null) { - isCollection = false; + /** + * Core value-processing logic. Interprets the given value and populates the appropriate internal + * fields ({@code childTraversals}, {@code literals}, {@code variables}, {@code isCollection}). + * Does NOT reset state first — the caller is responsible for ensuring a clean slate if needed. + */ + @SuppressWarnings("unchecked") + private void applyValue(final V value) { + if (value instanceof GraphTraversal) { + final Traversal.Admin admin = ((Traversal) value).asAdmin(); + ReadOnlyChildValidator.validate(admin); + this.childTraversals = Collections.singletonList(admin); + } else if (value == null) { this.literals = Collections.singleton(null); } else if (value instanceof GValue) { variables.put(((GValue) value).getName(), ((GValue) value).get()); - isCollection = false; } else if (value instanceof Collection) { - isCollection = true; - if (((Collection) value).stream().anyMatch(v -> v instanceof GValue)) { + final Collection coll = (Collection) value; + if (!coll.isEmpty() && coll.stream().anyMatch(v -> v instanceof GraphTraversal)) { + if (!coll.stream().allMatch(v -> v instanceof GraphTraversal)) { + throw new IllegalArgumentException( + "Cannot mix traversals and literal values. " + + "Use __.constant(val) to wrap each value as a traversal."); + } + final List> admins = new ArrayList<>(coll.size()); + for (final Object t : coll) { + final Traversal.Admin admin = ((Traversal) t).asAdmin(); + ReadOnlyChildValidator.validate(admin); + admins.add(admin); + } + this.childTraversals = admins; + this.isCollection = true; + } else if (coll.stream().anyMatch(v -> v instanceof GValue)) { + isCollection = true; this.literals = (value instanceof BulkSet) ? new BulkSet<>() : new ArrayList<>(); - for (Object v : ((Collection) value)) { - // Separate variables and literals + for (final Object v : coll) { if (v instanceof GValue) { if (((GValue) v).isVariable()) { variables.put(((GValue) v).getName(), ((GValue) v).get()); @@ -142,16 +202,17 @@ public void setValue(final V value) { } } } else { - literals = (Collection) value; // Retain original collection when possible + isCollection = true; + literals = (Collection) value; } } else { - isCollection = false; this.literals = Collections.singleton(value); } } @Override public boolean test(final V testValue) { + if (this.resolvedEmpty) return false; return this.biPredicate.test(testValue, this.getValue()); } @@ -162,6 +223,8 @@ public int hashCode() { result ^= this.variables.hashCode(); if (null != this.literals) result ^= this.literals.hashCode(); + if (null != this.childTraversals) + result ^= this.childTraversals.hashCode(); return result; } @@ -171,7 +234,8 @@ public boolean equals(final Object other) { ((P) other).getClass().equals(this.getClass()) && ((P) other).getBiPredicate().equals(this.biPredicate) && ((((P) other).variables == null && this.variables == null) || (((P) other).variables != null && ((P) other).variables.equals(this.variables))) && - ((((P) other).literals == null && this.literals == null) || (((P) other).literals != null && CollectionUtils.isEqualCollection(((P) other).literals, this.literals))); + ((((P) other).literals == null && this.literals == null) || (((P) other).literals != null && CollectionUtils.isEqualCollection(((P) other).literals, this.literals))) && + Objects.equals(((P) other).childTraversals, this.childTraversals); } @Override @@ -200,7 +264,14 @@ public P or(final Predicate predicate) { public P clone() { try { - return (P) super.clone(); + final P clone = (P) super.clone(); + if (this.childTraversals != null) { + clone.childTraversals = new ArrayList<>(this.childTraversals.size()); + for (final Traversal.Admin tv : this.childTraversals) { + clone.childTraversals.add(tv.clone()); + } + } + return clone; } catch (final CloneNotSupportedException e) { throw new IllegalStateException(e.getMessage(), e); } @@ -224,6 +295,118 @@ public Set> getGValues() { return results; } + /** + * Determines if this predicate holds a child traversal whose result is resolved at runtime. + */ + public boolean hasTraversal() { + return this.childTraversals != null && !this.childTraversals.isEmpty(); + } + + /** + * Returns {@code true} if the most recent call to {@link #resolve(Traverser.Admin)} produced no results + * for a scalar predicate, meaning there is no meaningful comparison value. + */ + public boolean isResolvedEmpty() { + return this.resolvedEmpty; + } + + /** + * Gets the child traversals held by this predicate. Returns {@code null} when this predicate uses + * literal values or variables. + * + * @since 4.0.0 + */ + public List> getChildTraversals() { + return this.childTraversals; + } + + /** + * Resolves the child traversal(s) against the given traverser, replacing the traversal value with the + * resolved literal(s) for this test cycle. If no traversal is present, this method returns immediately. + */ + @SuppressWarnings("unchecked") + public void resolve(final Traverser.Admin traverser) { + if (this.childTraversals == null || this.childTraversals.isEmpty()) return; + + // Evaluate each child traversal, taking the first result from each. + final List results = new ArrayList<>(); + for (final Traversal.Admin tv : this.childTraversals) { + prepareChildTraversal(traverser, (Traversal.Admin) tv); + try { + if (tv.hasNext()) { + results.add(tv.next()); + } + } finally { + CloseableIterator.closeIterator(tv); + } + } + + // Empty result: for collection predicates resolve to empty set; for scalar predicates short-circuit. + if (results.isEmpty()) { + if (this.isCollection) { + this.resolvedEmpty = false; + this.variables.clear(); + this.literals = Collections.emptyList(); + } else { + this.resolvedEmpty = true; + } + return; + } + + this.resolvedEmpty = false; + this.variables.clear(); + this.literals = Collections.EMPTY_LIST; + + if (this.isCollection) { + // Collection predicate (within, without). Unfold if there is only a single + // child traversal which yields a list. + if (this.childTraversals.size() == 1) { + final Object r = results.get(0); + if (r instanceof Collection) { + applyValue((V) new ArrayList<>((Collection) r)); + } else { + applyValue((V) Collections.singletonList(r)); + } + } else { + // Multiple child traversals — each contributes its first result as one element, as-is. + applyValue((V) new ArrayList<>(results)); + } + } else { + // Scalar predicate (eq, gt, etc.) — pass single result directly. + applyValue((V) results.get(0)); + } + } + + /** + * Prepares a child traversal for evaluation by splitting the current traverser and seeding it. + */ + @SuppressWarnings("unchecked") + private static void prepareChildTraversal(final Traverser.Admin traverser, final Traversal.Admin trav) { + final Traverser.Admin split = (Traverser.Admin) traverser.split(); + split.setSideEffects(trav.getSideEffects()); + split.setBulk(1L); + trav.reset(); + trav.addStart(split); + } + + //////////////// predicate traversal utilities + + /** + * Recursively collects all child traversals from a predicate tree. + * Handles {@link ConnectiveP} (recurses into children) and {@link NotP} (recurses into wrapped predicate). + */ + public static void collectTraversals(final P p, final List> traversals) { + if (p instanceof ConnectiveP) { + for (final P child : ((ConnectiveP) p).getPredicates()) { + collectTraversals(child, traversals); + } + } else if (p instanceof NotP) { + collectTraversals(((NotP) p).getWrapped(), traversals); + } else if (p.getChildTraversals() != null) { + traversals.addAll(p.getChildTraversals()); + } + } + //////////////// statics /** @@ -243,6 +426,15 @@ public static P eq(final GValue value) { return new P(Compare.eq, value); } + /** + * Determines if values are equal using a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P eq(final Traversal traversalValue) { + return new P(Compare.eq, traversalValue.asAdmin()); + } + /** * Determines if values are not equal. * @@ -261,6 +453,15 @@ public static P neq(final GValue value) { return new P(Compare.neq, value); } + /** + * Determines if values are not equal using a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P neq(final Traversal traversalValue) { + return new P(Compare.neq, traversalValue.asAdmin()); + } + /** * Determines if a value is less than another. * @@ -279,6 +480,15 @@ public static P lt(final GValue value) { return new P(Compare.lt, value); } + /** + * Determines if a value is less than another using a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P lt(final Traversal traversalValue) { + return new P(Compare.lt, traversalValue.asAdmin()); + } + /** * Determines if a value is less than or equal to another. * @@ -297,6 +507,15 @@ public static P lte(final GValue value) { return new P(Compare.lte, value); } + /** + * Determines if a value is less than or equal to another using a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P lte(final Traversal traversalValue) { + return new P(Compare.lte, traversalValue.asAdmin()); + } + /** * Determines if a value is greater than another. * @@ -315,6 +534,15 @@ public static P gt(final GValue value) { return new P(Compare.gt, value); } + /** + * Determines if a value is greater than another using a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P gt(final Traversal traversalValue) { + return new P(Compare.gt, traversalValue.asAdmin()); + } + /** * Determines if a value is greater than or equal to another. * @@ -333,6 +561,15 @@ public static P gte(final GValue value) { return new P(Compare.gte, value); } + /** + * Determines if a value is greater than or equal to another using a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P gte(final Traversal traversalValue) { + return new P(Compare.gte, traversalValue.asAdmin()); + } + /** * Determines if a value is within (exclusive) the range of the two specified values. * @@ -420,6 +657,30 @@ public static P within(final Collection value) { return new P(Contains.within, value); } + /** + * Determines if a value is within the results of a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P within(final Traversal traversalValue) { + return new P(Contains.within, Collections.singletonList(traversalValue.asAdmin())); + } + + /** + * Determines if a value is within the results of child traversals resolved at runtime. + * Each traversal is evaluated independently and results are combined into a single collection. + * + * @since 4.0.0 + */ + public static P within(final Traversal first, final Traversal... more) { + final List> admins = new ArrayList<>(1 + more.length); + admins.add(first.asAdmin()); + for (final Traversal tv : more) { + admins.add(tv.asAdmin()); + } + return new P(Contains.within, admins); + } + /** * Determines if a value is not within the specified list of values. If the array of arguments itself is {@code null} * then the argument is treated as {@code Object[1]} where that single value is {@code null}. @@ -453,6 +714,30 @@ public static P without(final Collection value) { return new P(Contains.without, value); } + /** + * Determines if a value is not within the results of a child traversal resolved at runtime. + * + * @since 4.0.0 + */ + public static P without(final Traversal traversalValue) { + return new P(Contains.without, Collections.singletonList(traversalValue.asAdmin())); + } + + /** + * Determines if a value is not within the results of child traversals resolved at runtime. + * Each traversal is evaluated independently and results are combined into a single collection. + * + * @since 4.0.0 + */ + public static P without(final Traversal first, final Traversal... more) { + final List> admins = new ArrayList<>(1 + more.length); + admins.add(first.asAdmin()); + for (final Traversal tv : more) { + admins.add(tv.asAdmin()); + } + return new P(Contains.without, admins); + } + /** * Determines if a value is of a type denoted by {@code GType}. * diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java index d1d8c210197..8ec80a7c623 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java @@ -38,6 +38,16 @@ public TextP(final PBiPredicate biPredicate, final GValue biPredicate, final Traversal.Admin traversalValue) { + super(biPredicate, traversalValue); + } + protected TextP(final PBiPredicate biPredicate, final Collection literals, final Map variables) { super(biPredicate, literals, variables, false); } @@ -76,6 +86,15 @@ public static TextP startingWith(final GValue value) { return new TextP(Text.startingWith, value); } + /** + * Determines if String does start with the value resolved from a child traversal at runtime. + * + * @since 4.0.0 + */ + public static TextP startingWith(final Traversal traversalValue) { + return new TextP(Text.startingWith, traversalValue.asAdmin()); + } + /** * Determines if String does not start with the given value. * @@ -95,7 +114,16 @@ public static TextP notStartingWith(final GValue value) { } /** - * Determines if String does start with the given value. + * Determines if String does not start with the value resolved from a child traversal at runtime. + * + * @since 4.0.0 + */ + public static TextP notStartingWith(final Traversal traversalValue) { + return new TextP(Text.notStartingWith, traversalValue.asAdmin()); + } + + /** + * Determines if String does end with the given value. * * @since 3.4.0 */ @@ -104,7 +132,7 @@ public static TextP endingWith(final String value) { } /** - * Determines if String does start with the given value. + * Determines if String does end with the given value. * * @since 3.8.0 */ @@ -113,7 +141,16 @@ public static TextP endingWith(final GValue value) { } /** - * Determines if String does not start with the given value. + * Determines if String does end with the value resolved from a child traversal at runtime. + * + * @since 4.0.0 + */ + public static TextP endingWith(final Traversal traversalValue) { + return new TextP(Text.endingWith, traversalValue.asAdmin()); + } + + /** + * Determines if String does not end with the given value. * * @since 3.4.0 */ @@ -122,7 +159,7 @@ public static TextP notEndingWith(final String value) { } /** - * Determines if String does not start with the given value. + * Determines if String does not end with the given value. * * @since 3.8.0 */ @@ -130,6 +167,15 @@ public static TextP notEndingWith(final GValue value) { return new TextP(Text.notEndingWith, value); } + /** + * Determines if String does not end with the value resolved from a child traversal at runtime. + * + * @since 4.0.0 + */ + public static TextP notEndingWith(final Traversal traversalValue) { + return new TextP(Text.notEndingWith, traversalValue.asAdmin()); + } + /** * Determines if String does contain the given value. * @@ -148,6 +194,15 @@ public static TextP containing(final GValue value) { return new TextP(Text.containing, value); } + /** + * Determines if String does contain the value resolved from a child traversal at runtime. + * + * @since 4.0.0 + */ + public static TextP containing(final Traversal traversalValue) { + return new TextP(Text.containing, traversalValue.asAdmin()); + } + /** * Determines if String does not contain the given value. * @@ -165,6 +220,15 @@ public static TextP notContaining(final String value) { public static TextP notContaining(final GValue value) { return new TextP(Text.notContaining, value); } + + /** + * Determines if String does not contain the value resolved from a child traversal at runtime. + * + * @since 4.0.0 + */ + public static TextP notContaining(final Traversal traversalValue) { + return new TextP(Text.notContaining, traversalValue.asAdmin()); + } /** * Determines if String has a match with the given regex pattern. The TinkerPop reference implementation uses 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 df50a92462e..de863361040 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 @@ -210,6 +210,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics; +import org.apache.tinkerpop.gremlin.process.traversal.util.ReadOnlyChildValidator; import org.apache.tinkerpop.gremlin.structure.Column; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; @@ -415,6 +416,21 @@ public default GraphTraversal V(final Object... vertexIdsOrElements) return this.asAdmin().addStep(step); } + /** + * A {@code V} step that accepts a child traversal whose results are used as vertex IDs for lookup. + * + * @param traversal the child traversal that produces vertex IDs + * @return the traversal with an appended {@link GraphStep} + * @see Reference Documentation - Graph Step + * @since 4.0.0 + */ + public default GraphTraversal V(final Traversal traversal) { + if (null == traversal) return V(new Object[]{ null }); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.V, traversal); + return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), Vertex.class, false, traversal.asAdmin())); + } + /** * A {@code E} step is usually used to start a traversal but it may also be used mid-traversal. * @@ -438,6 +454,21 @@ public default GraphTraversal E(final Object... edgeIdsOrElements) { return this.asAdmin().addStep(step); } + /** + * A {@code E} step that accepts a child traversal whose results are used as edge IDs for lookup. + * + * @param traversal the child traversal that produces edge IDs + * @return the traversal with an appended {@link GraphStep} + * @see Reference Documentation - E Step + * @since 4.0.0 + */ + public default GraphTraversal E(final Traversal traversal) { + if (null == traversal) return E(new Object[]{ null }); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.E, traversal); + return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), Edge.class, false, traversal.asAdmin())); + } + /** * Map the {@link Vertex} to its adjacent vertices given a direction. * @@ -2706,6 +2737,47 @@ public default GraphTraversal has(final T accessor, final Object value) { } } + /** + * Filters vertices, edges and vertex properties based on their properties using a child traversal + * whose results are resolved at runtime against the current traverser. The resolved results are used + * with {@code P.within()} semantics for comparison against the named property. + * + * @param propertyKey the key of the property to filter on + * @param traversal the child traversal whose results are used as the filter value + * @return the traversal with an appended {@link HasStep} + * @see Reference Documentation - Has Step + * @since 4.0.0 + */ + public default GraphTraversal has(final String propertyKey, final Traversal traversal) { + if (null == traversal) return has(propertyKey, (Object) null); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.has, propertyKey, traversal); + final HasContainer hasContainer = new HasContainer(propertyKey, P.eq(traversal.asAdmin())); + return this.asAdmin().addStep(new HasStep(this.asAdmin(), hasContainer)); + } + + /** + * Filters vertices, edges and vertex properties based on their properties using a child traversal + * whose results are resolved at runtime against the current traverser. The resolved results are used + * with {@code P.within()} semantics for comparison against the T-accessor value (id or label). + * + * @param accessor the {@link T} accessor of the property to filter on + * @param traversal the child traversal whose results are used as the filter value + * @return the traversal with an appended {@link HasStep} + * @see Reference Documentation - Has Step + * @since 4.0.0 + */ + public default GraphTraversal has(final T accessor, final Traversal traversal) { + if (null == accessor) + throw new IllegalArgumentException("The T accessor value of has(T,Traversal) cannot be null"); + if (null == traversal) return has(accessor, (Object) null); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + + this.asAdmin().getGremlinLang().addStep(Symbols.has, accessor, traversal); + final HasContainer hasContainer = new HasContainer(accessor.getAccessor(), P.eq(traversal.asAdmin())); + return this.asAdmin().addStep(new HasStep(this.asAdmin(), hasContainer)); + } + /** * Filters vertices, edges and vertex properties based on their properties. * @@ -2738,6 +2810,27 @@ public default GraphTraversal has(final String label, final String propert return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value))); } + /** + * Filters vertices, edges and vertex properties based on their label and a property value resolved + * from a child traversal at runtime. The label is matched first, then the child traversal results + * are used with {@code P.within()} semantics for comparison against the named property. + * + * @param label the label of the {@link Element} + * @param propertyKey the key of the property to filter on + * @param traversal the child traversal whose results are used as the filter value + * @return the traversal with an appended {@link HasStep} + * @see Reference Documentation - Has Step + * @since 4.0.0 + */ + public default GraphTraversal has(final String label, final String propertyKey, final Traversal traversal) { + if (null == traversal) return has(label, propertyKey, (Object) null); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.has, label, propertyKey, traversal); + TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), P.eq(label))); + final HasContainer hasContainer = new HasContainer(propertyKey, P.eq(traversal.asAdmin())); + return this.asAdmin().addStep(new HasStep(this.asAdmin(), hasContainer)); + } + /** * Filters vertices, edges and vertex properties based on the existence of properties. * @@ -2833,6 +2926,23 @@ public default GraphTraversal hasLabel(final P predicate) { } } + /** + * Filters vertices, edges and vertex properties based on their label using a child traversal + * whose results are resolved at runtime against the current traverser. + * + * @param traversal the child traversal whose results are used as the label filter value + * @return the traversal with an appended {@link HasStep} + * @see Reference Documentation - Has Step + * @since 4.0.0 + */ + public default GraphTraversal hasLabel(final Traversal traversal) { + if (null == traversal) return hasLabel((String) null); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.hasLabel, traversal); + final HasContainer hasContainer = new HasContainer(T.label.getAccessor(), P.eq(traversal.asAdmin())); + return this.asAdmin().addStep(new HasStep(this.asAdmin(), hasContainer)); + } + /** * Filters vertices, edges and vertex properties based on their label. * @@ -2980,6 +3090,23 @@ public default GraphTraversal hasKey(final P predicate) { } } + /** + * Filters {@link Property} objects based on their key using a child traversal whose results are resolved at + * runtime against the current traverser. + * + * @param traversal the child traversal whose results are used as the key filter value + * @return the traversal with an appended {@link HasStep} + * @see Reference Documentation - Has Step + * @since 4.0.0 + */ + public default GraphTraversal hasKey(final Traversal traversal) { + if (null == traversal) return hasKey((String) null); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.hasKey, traversal); + final HasContainer hasContainer = new HasContainer(T.key.getAccessor(), P.eq(traversal.asAdmin())); + return this.asAdmin().addStep(new HasStep(this.asAdmin(), hasContainer)); + } + /** * Filters {@link Property} objects based on their value. * @@ -3034,6 +3161,23 @@ public default GraphTraversal hasValue(final P predicate) { } } + /** + * Filters {@link Property} objects based on their value using a child traversal whose results are resolved at + * runtime against the current traverser. + * + * @param traversal the child traversal whose results are used as the value filter + * @return the traversal with an appended {@link HasStep} + * @see Reference Documentation - Has Step + * @since 4.0.0 + */ + public default GraphTraversal hasValue(final Traversal traversal) { + if (null == traversal) return hasValue((Object) null); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.hasValue, traversal); + final HasContainer hasContainer = new HasContainer(T.value.getAccessor(), P.eq(traversal.asAdmin())); + return this.asAdmin().addStep(new HasStep(this.asAdmin(), hasContainer)); + } + /** * Filters E object values given the provided {@code predicate}. * @@ -3058,7 +3202,14 @@ public default GraphTraversal is(final P predicate) { */ public default GraphTraversal is(final Object value) { this.asAdmin().getGremlinLang().addStep(Symbols.is, value); - P predicate = value instanceof P ? (P) value : P.eq((E) value); + P predicate; + if (value instanceof P) { + predicate = (P) value; + } else if (value instanceof Traversal) { + predicate = (P) P.eq(((Traversal) value).asAdmin()); + } else { + predicate = P.eq((E) value); + } return this.asAdmin().addStep(predicate.isParameterized() ? new IsStepPlaceholder<>(this.asAdmin(), predicate) : new IsStep<>(this.asAdmin(), predicate)); } @@ -3861,6 +4012,25 @@ public default GraphTraversal property(final Map value) { } return this; } + + /** + * Sets properties on the current element using a child traversal that produces a {@code Map}. + * Each entry in the resulting Map becomes a property (key → value) on the element. The traversal + * is evaluated at execution time against the current traverser. + * + * @param mapTraversal a traversal that produces a {@code Map} of property key/value pairs + * @return the traversal with the {@link AddPropertyStepPlaceholder} added + * @see AddProperty Step + * @since 4.0.0 + */ + public default GraphTraversal property(final Traversal mapTraversal) { + if (null == mapTraversal) return this; + ReadOnlyChildValidator.validate(mapTraversal.asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.property, mapTraversal); + this.asAdmin().addStep(new AddPropertyStepPlaceholder(this.asAdmin(), null, null, mapTraversal.asAdmin(), true)); + return this; + } + ///////////////////// BRANCH STEPS ///////////////////// /** @@ -3995,6 +4165,9 @@ public default GraphTraversal choose(final Predicate choosePredic /** * Routes the current traverser to a particular traversal branch option which allows the creation of if-then-else * like semantics within a traversal. + *

+ * Note: Traversal-bearing predicates (e.g. {@code P.gt(__.V(1).values("age"))}) are not supported in + * {@code choose()} and will throw an {@code IllegalArgumentException}. * * @param choosePredicate the {@link P} used to determine the "if" portion of the if-then-else * @param trueChoice the traversal to execute in the event the {@code traversalPredicate} returns true @@ -4008,6 +4181,10 @@ public default GraphTraversal choose(final P choosePredicate, if (choosePredicate.isParameterized()) { throw new IllegalArgumentException("Parameterized predicates are not supported by choose()"); } + if (choosePredicate.hasTraversal()) { + throw new IllegalArgumentException("Traversal-bearing predicates are not supported by choose(). " + + "The predicate's child traversal cannot be resolved in this context."); + } this.asAdmin().getGremlinLang().addStep(Symbols.choose, choosePredicate, trueChoice, falseChoice); return this.asAdmin().addStep(new ChooseStep(this.asAdmin(), (Traversal.Admin) __.is(choosePredicate), (Traversal.Admin) trueChoice, (Traversal.Admin) falseChoice)); } @@ -4033,6 +4210,9 @@ public default GraphTraversal choose(final Predicate choosePredic /** * Routes the current traverser to a particular traversal branch option which allows the creation of if-then * like semantics within a traversal. + *

+ * Note: Traversal-bearing predicates (e.g. {@code P.gt(__.V(1).values("age"))}) are not supported in + * {@code choose()} and will throw an {@code IllegalArgumentException}. * * @param choosePredicate the {@link P} used to determine the "if" portion of the if-then-else * @param trueChoice the traversal to execute in the event the {@code traversalPredicate} returns true @@ -4045,6 +4225,10 @@ public default GraphTraversal choose(final P choosePredicate, if (choosePredicate.isParameterized()) { throw new IllegalArgumentException("Parameterized predicates are not supported by choose()"); } + if (choosePredicate.hasTraversal()) { + throw new IllegalArgumentException("Traversal-bearing predicates are not supported by choose(). " + + "The predicate's child traversal cannot be resolved in this context."); + } this.asAdmin().getGremlinLang().addStep(Symbols.choose, choosePredicate, trueChoice); return this.asAdmin().addStep(new ChooseStep(this.asAdmin(), (Traversal.Admin) __.is(choosePredicate), (Traversal.Admin) trueChoice, (Traversal.Admin) __.identity())); } @@ -4580,6 +4764,9 @@ public default GraphTraversal by(final Function function, f * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see * the documentation of such steps to understand the usage context. + *

+ * Note: When used with {@code choose()}, traversal-bearing predicates are not supported as option tokens + * and will throw an {@code IllegalArgumentException}. * * @param token the token that would trigger this option which may be a {@link Pick}, {@link Merge}, * a {@link Traversal}, {@link Predicate}, or object depending on the step being modulated. diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java index fa9be0a639e..07ccbe0b240 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java @@ -43,6 +43,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStepContract; import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.RequirementsStrategy; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; +import org.apache.tinkerpop.gremlin.process.traversal.util.ReadOnlyChildValidator; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Graph; @@ -547,6 +548,24 @@ public GraphTraversal V(final Object... vertexIds) { return traversal.addStep(step); } + /** + * Spawns a {@link GraphTraversal} starting with vertices whose IDs are resolved from a child traversal. + * As a start step, a synthetic traverser is generated to seed the child traversal evaluation, + * consistent with how {@code mergeV(traversal)} handles start steps. The child traversal should + * be self-contained (e.g., {@code __.V(1).id()}) rather than dependent on an incoming traverser. + * + * @param traversal the child traversal that produces vertex IDs + * @since 4.0.0 + */ + public GraphTraversal V(final Traversal traversal) { + if (null == traversal) return V(new Object[]{ null }); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + final GraphTraversalSource clone = this.clone(); + clone.gremlinLang.addStep(GraphTraversal.Symbols.V, traversal); + final GraphTraversal.Admin traversalAdmin = new DefaultGraphTraversal<>(clone); + return traversalAdmin.addStep(new GraphStep<>(traversalAdmin, Vertex.class, true, traversal.asAdmin())); + } + /** * Spawns a {@link GraphTraversal} starting with all edges or some subset of edges as specified by their unique * identifier. @@ -568,6 +587,24 @@ public GraphTraversal E(final Object... edgeIds) { return traversal.addStep(step); } + /** + * Spawns a {@link GraphTraversal} starting with edges whose IDs are resolved from a child traversal. + * As a start step, a synthetic traverser is generated to seed the child traversal evaluation, + * consistent with how {@code mergeE(traversal)} handles start steps. The child traversal should + * be self-contained (e.g., {@code __.V(1).outE().id()}) rather than dependent on an incoming traverser. + * + * @param traversal the child traversal that produces edge IDs + * @since 4.0.0 + */ + public GraphTraversal E(final Traversal traversal) { + if (null == traversal) return E(new Object[]{ null }); + ReadOnlyChildValidator.validate(traversal.asAdmin()); + final GraphTraversalSource clone = this.clone(); + clone.gremlinLang.addStep(GraphTraversal.Symbols.E, traversal); + final GraphTraversal.Admin traversalAdmin = new DefaultGraphTraversal<>(clone); + return traversalAdmin.addStep(new GraphStep<>(traversalAdmin, Edge.class, true, traversal.asAdmin())); + } + /** * Spawns a {@link GraphTraversal} starting with a list of available services. * diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java index 390c4cc48fb..10ff3724186 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java @@ -142,6 +142,13 @@ public static GraphTraversal V(final Object... vertexIdsOrElement return __.start().V(vertexIdsOrElements); } + /** + * @see GraphTraversal#V(Traversal) + */ + public static GraphTraversal V(final Traversal traversal) { + return __.start().V(traversal); + } + /** * @see GraphTraversal#E(Object...) */ @@ -149,6 +156,13 @@ public static GraphTraversal E(final Object... edgeIdsOrElements) { return __.start().E(edgeIdsOrElements); } + /** + * @see GraphTraversal#E(Traversal) + */ + public static GraphTraversal E(final Traversal traversal) { + return __.start().E(traversal); + } + /** * @see GraphTraversal#to(Direction) */ @@ -1110,6 +1124,13 @@ public static GraphTraversal has(final String propertyKey, final P return __.start().has(propertyKey, predicate); } + /** + * @see GraphTraversal#has(String, Traversal) + */ + public static GraphTraversal has(final String propertyKey, final Traversal traversal) { + return __.start().has(propertyKey, traversal); + } + /** * @see GraphTraversal#has(T, P) */ @@ -1131,6 +1152,13 @@ public static GraphTraversal has(final T accessor, final Object value) return __.start().has(accessor, value); } + /** + * @see GraphTraversal#has(T, Traversal) + */ + public static GraphTraversal has(final T accessor, final Traversal traversal) { + return __.start().has(accessor, traversal); + } + /** * @see GraphTraversal#has(String, String, Object) */ @@ -1160,6 +1188,13 @@ public static GraphTraversal has(final String label, final String prop return __.start().has(label, propertyKey, predicate); } + /** + * @see GraphTraversal#has(String, String, Traversal) + */ + public static GraphTraversal has(final String label, final String propertyKey, final Traversal traversal) { + return __.start().has(label, propertyKey, traversal); + } + /** * @see GraphTraversal#has(String) */ @@ -1195,6 +1230,13 @@ public static GraphTraversal hasLabel(final P predicate) { return __.start().hasLabel(predicate); } + /** + * @see GraphTraversal#hasLabel(Traversal) + */ + public static GraphTraversal hasLabel(final Traversal traversal) { + return __.start().hasLabel(traversal); + } + /** * @see GraphTraversal#hasId(Object, Object...) */ @@ -1223,6 +1265,13 @@ public static GraphTraversal hasKey(final P predicate) { return __.start().hasKey(predicate); } + /** + * @see GraphTraversal#hasKey(Traversal) + */ + public static GraphTraversal hasKey(final Traversal traversal) { + return __.start().hasKey(traversal); + } + /** * @see GraphTraversal#hasValue(Object, Object...) */ @@ -1237,6 +1286,13 @@ public static GraphTraversal hasValue(final P predicate) { return __.start().hasValue(predicate); } + /** + * @see GraphTraversal#hasValue(Traversal) + */ + public static GraphTraversal hasValue(final Traversal traversal) { + return __.start().hasValue(traversal); + } + /** * @see GraphTraversal#where(String, P) */ @@ -1576,6 +1632,13 @@ public static GraphTraversal property(final Map value) return __.start().property(value); } + /** + * @see GraphTraversal#property(Traversal) + */ + public static GraphTraversal property(final Traversal mapTraversal) { + return __.start().property(mapTraversal); + } + ///////////////////// BRANCH STEPS ///////////////////// /** diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ReadOnlyTraversalParent.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ReadOnlyTraversalParent.java new file mode 100644 index 00000000000..50b255fd269 --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ReadOnlyTraversalParent.java @@ -0,0 +1,34 @@ +/* + * 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. + */ +package org.apache.tinkerpop.gremlin.process.traversal.step; + +/** + * Marker interface for {@link TraversalParent} steps whose child traversals must be read-only + * (no mutating steps allowed). Examples include {@code has(key, traversal)}, + * {@code is(P.gt(traversal))}, {@code V(traversal)}, and {@code property(traversal)}. + *

+ * The {@link org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy} + * validates the children of every step implementing this interface, rejecting child traversals that + * contain mutating steps. New steps that accept such traversals should implement this interface so they are + * validated automatically rather than relying on a hardcoded step list. + * + * @since 4.0.0 + */ +public interface ReadOnlyTraversalParent extends TraversalParent { +} diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java index 73bec11d64d..c84028f9017 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java @@ -18,6 +18,7 @@ */ package org.apache.tinkerpop.gremlin.process.traversal.step.branch; +import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Pick; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal; @@ -122,6 +123,10 @@ public void addChildOption(final M pickToken, final Traversal.Admin traver } } else if (pickToken instanceof Traversal) { throw new IllegalArgumentException("Traversal is not allowed as a Pick token for choose().option()"); + } else if (pickToken instanceof P && ((P) pickToken).hasTraversal()) { + throw new IllegalArgumentException( + "Traversal-bearing predicates are not supported as option keys in choose(). " + + "The predicate's child traversal cannot be resolved in this context."); } else { super.addChildOption(pickToken, traversalOption); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AllStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AllStep.java index 64853f6614f..3dfaceb9f1c 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AllStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AllStep.java @@ -21,15 +21,18 @@ import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; -import java.util.EnumSet; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Set; -public final class AllStep extends FilterStep { +public final class AllStep extends FilterStep implements ReadOnlyTraversalParent { private P predicate; @@ -45,6 +48,10 @@ public AllStep(final Traversal.Admin traversal, final P predicate) { @Override protected boolean filter(final Traverser.Admin traverser) { + if (this.predicate.hasTraversal()) { + this.predicate.resolve(traverser); + } + final S item = traverser.get(); if (item instanceof Iterable || item instanceof Iterator || ((item != null) && item.getClass().isArray())) { @@ -65,6 +72,13 @@ public String toString() { return StringFactory.stepString(this, this.predicate); } + @Override + public List> getLocalChildren() { + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + return (List) Collections.unmodifiableList(traversals); + } + @Override public AllStep clone() { final AllStep clone = (AllStep) super.clone(); @@ -74,6 +88,14 @@ public AllStep clone() { @Override public Set getRequirements() { - return EnumSet.of(TraverserRequirement.OBJECT); + return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT); + } + + @Override + public void setTraversal(final Traversal.Admin parentTraversal) { + super.setTraversal(parentTraversal); + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + traversals.forEach(this::integrateChild); } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AnyStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AnyStep.java index 9881186d7ca..d667e09eb2b 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AnyStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AnyStep.java @@ -21,15 +21,18 @@ import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; -import java.util.EnumSet; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Set; -public final class AnyStep extends FilterStep { +public final class AnyStep extends FilterStep implements ReadOnlyTraversalParent { private P predicate; @@ -45,6 +48,10 @@ public AnyStep(final Traversal.Admin traversal, final P predicate) { @Override protected boolean filter(final Traverser.Admin traverser) { + if (this.predicate.hasTraversal()) { + this.predicate.resolve(traverser); + } + final S item = traverser.get(); if (item instanceof Iterable || item instanceof Iterator || ((item != null) && item.getClass().isArray())) { @@ -65,6 +72,13 @@ public String toString() { return StringFactory.stepString(this, this.predicate); } + @Override + public List> getLocalChildren() { + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + return (List) Collections.unmodifiableList(traversals); + } + @Override public AnyStep clone() { final AnyStep clone = (AnyStep) super.clone(); @@ -74,6 +88,14 @@ public AnyStep clone() { @Override public Set getRequirements() { - return EnumSet.of(TraverserRequirement.OBJECT); + return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT); + } + + @Override + public void setTraversal(final Traversal.Admin parentTraversal) { + super.setTraversal(parentTraversal); + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + traversals.forEach(this::integrateChild); } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java index e7ef0095657..ec327e01c3e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java @@ -18,8 +18,10 @@ */ package org.apache.tinkerpop.gremlin.process.traversal.step.filter; +import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring; import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder; import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer; @@ -31,22 +33,25 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.EnumSet; import java.util.List; import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public class HasStep extends FilterStep implements HasContainerHolder, Configuring { +public class HasStep extends FilterStep implements HasContainerHolder, Configuring, ReadOnlyTraversalParent { private final Parameters parameters = new Parameters(); private List hasContainers; + private List> childTraversals = new ArrayList<>(); public HasStep(final Traversal.Admin traversal, final HasContainer... hasContainers) { super(traversal); this.hasContainers = new ArrayList<>(); - Collections.addAll(this.hasContainers, hasContainers); + for (final HasContainer hc : hasContainers) { + this.hasContainers.add(hc); + collectChildTraversals(hc); + } } @Override @@ -63,14 +68,58 @@ public void configure(final Object... keyValues) { protected boolean filter(final Traverser.Admin traverser) { // the generic S is defined as Element but Property can also be used with HasStep so this seems to cause // problems with some jdk versions. - if (traverser.get() instanceof Element) - return HasContainer.testAll(traverser.get(), this.hasContainers); - else if (traverser.get() instanceof Property) - return HasContainer.testAll((Property) traverser.get(), this.hasContainers); - else + // Check Property BEFORE Element because VertexProperty implements both interfaces. + // HasContainer.test(Property) correctly handles T.key and T.value accessors, whereas + // HasContainer.test(Element) would fall through to element.properties("~key") which fails. + if (traverser.get() instanceof Property) { + return testAllWithTraversals(traverser, (Property) traverser.get()); + } else if (traverser.get() instanceof Element) { + return testAllWithTraversals(traverser, (Element) traverser.get()); + } else { throw new IllegalStateException(String.format( "Traverser to has() must be of type Property or Element, not %s", traverser.get().getClass().getName())); + } + } + + /** + * Tests all HasContainers against an Element. Traversal-bearing containers carry a {@code P} predicate + * (e.g. {@code P.eq(traversal)}) whose child traversal is resolved against the current traverser before + * the standard {@link HasContainer#test(Element)} is applied. + */ + private boolean testAllWithTraversals(final Traverser.Admin traverser, final Element element) { + for (final HasContainer hc : this.hasContainers) { + if (hc.hasTraversal()) hc.getPredicate().resolve(traverser); + if (!hc.test(element)) { + return false; + } + } + return true; + } + + /** + * Tests all HasContainers against a Property. See {@link #testAllWithTraversals(Traverser.Admin, Element)}. + */ + private boolean testAllWithTraversals(final Traverser.Admin traverser, final Property property) { + for (final HasContainer hc : this.hasContainers) { + if (hc.hasTraversal()) hc.getPredicate().resolve(traverser); + if (!hc.test(property)) { + return false; + } + } + return true; + } + + /** + * Collects the child traversals embedded within a HasContainer's predicate (including + * {@link org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP}, which may carry traversals on + * child predicates) into {@link #childTraversals}. Parenting is deferred to + * {@link #setTraversal(Traversal.Admin)} which is the single integration point. + */ + private void collectChildTraversals(final HasContainer hc) { + if (hc.getPredicate().hasTraversal()) { + P.collectTraversals(hc.getPredicate(), this.childTraversals); + } } @Override @@ -91,23 +140,48 @@ public void removeHasContainer(final HasContainer hasContainer) { @Override public void addHasContainer(final HasContainer hasContainer) { this.hasContainers.add(hasContainer); + // A container may be added after this step has already been parented (e.g. by a strategy), so collect + // its child traversals and integrate just those new ones immediately. + final int before = this.childTraversals.size(); + collectChildTraversals(hasContainer); + for (int i = before; i < this.childTraversals.size(); i++) { + this.integrateChild(this.childTraversals.get(i)); + } + } + + @Override + public List> getLocalChildren() { + return (List) Collections.unmodifiableList(this.childTraversals); } @Override public Set getRequirements() { - return EnumSet.of(TraverserRequirement.OBJECT); + return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT); } @Override public HasStep clone() { final HasStep clone = (HasStep) super.clone(); clone.hasContainers = new ArrayList<>(); + clone.childTraversals = new ArrayList<>(); for (final HasContainer hasContainer : this.hasContainers) { - clone.addHasContainer(hasContainer.clone()); + final HasContainer clonedHc = hasContainer.clone(); + clone.hasContainers.add(clonedHc); + if (clonedHc.getPredicate().hasTraversal()) { + P.collectTraversals(clonedHc.getPredicate(), clone.childTraversals); + } } return clone; } + @Override + public void setTraversal(final Traversal.Admin parentTraversal) { + super.setTraversal(parentTraversal); + for (final Traversal.Admin childTraversal : this.childTraversals) { + this.integrateChild(childTraversal); + } + } + @Override public int hashCode() { int result = super.hashCode(); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java index 70ad55ff318..e65a9399744 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java @@ -21,17 +21,20 @@ import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; -import java.util.EnumSet; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Set; /** * @author Daniel Kuppitz (http://gremlin.guru) * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public final class IsStep extends FilterStep implements IsStepContract { +public final class IsStep extends FilterStep implements IsStepContract, ReadOnlyTraversalParent { private P predicate; @@ -42,6 +45,9 @@ public IsStep(final Traversal.Admin traversal, final P predicate) { @Override protected boolean filter(final Traverser.Admin traverser) { + if (this.predicate.hasTraversal()) { + this.predicate.resolve(traverser); + } return this.predicate.test(traverser.get()); } @@ -55,6 +61,13 @@ public P getPredicate() { return this.predicate; } + @Override + public List> getLocalChildren() { + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + return (List) Collections.unmodifiableList(traversals); + } + @Override public IsStep clone() { final IsStep clone = (IsStep) super.clone(); @@ -69,7 +82,14 @@ public int hashCode() { @Override public Set getRequirements() { - return EnumSet.of(TraverserRequirement.OBJECT); + return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT); } + @Override + public void setTraversal(final Traversal.Admin parentTraversal) { + super.setTraversal(parentTraversal); + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + traversals.forEach(this::integrateChild); + } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java index 542d16ca5c2..a5f329240b1 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java @@ -21,15 +21,18 @@ import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; -import java.util.EnumSet; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Set; -public final class NoneStep extends FilterStep { +public final class NoneStep extends FilterStep implements ReadOnlyTraversalParent { private P predicate; @@ -45,6 +48,10 @@ public NoneStep(final Traversal.Admin traversal, final P predicate) { @Override protected boolean filter(final Traverser.Admin traverser) { + if (this.predicate.hasTraversal()) { + this.predicate.resolve(traverser); + } + final S item = traverser.get(); if (item instanceof Iterable || item instanceof Iterator || ((item != null) && item.getClass().isArray())) { @@ -65,6 +72,13 @@ public String toString() { return StringFactory.stepString(this, this.predicate); } + @Override + public List> getLocalChildren() { + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + return (List) Collections.unmodifiableList(traversals); + } + @Override public NoneStep clone() { final NoneStep clone = (NoneStep) super.clone(); @@ -74,6 +88,14 @@ public NoneStep clone() { @Override public Set getRequirements() { - return EnumSet.of(TraverserRequirement.OBJECT); + return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT); + } + + @Override + public void setTraversal(final Traversal.Admin parentTraversal) { + super.setTraversal(parentTraversal); + final List> traversals = new ArrayList<>(); + P.collectTraversals(this.predicate, traversals); + traversals.forEach(this::integrateChild); } } 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 77c3f4abc98..968593894d4 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 @@ -22,10 +22,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.Pop; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating; import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor; import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping; -import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct; @@ -45,7 +45,7 @@ /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public final class WherePredicateStep extends FilterStep implements Scoping, PathProcessor, ByModulating, TraversalParent { +public final class WherePredicateStep extends FilterStep implements Scoping, PathProcessor, ByModulating, ReadOnlyTraversalParent { protected String startKey; protected List selectKeys; @@ -54,6 +54,7 @@ public final class WherePredicateStep extends FilterStep implements Scopin protected Set keepLabels; protected TraversalRing traversalRing = new TraversalRing<>(); + private List> predicateTraversals; public WherePredicateStep(final Traversal.Admin traversal, final Optional startKey, final P predicate) { super(traversal); @@ -63,12 +64,19 @@ public WherePredicateStep(final Traversal.Admin traversal, final Optional(); this.configurePredicates(this.predicate); + // Cache and integrate child traversals from the predicate + this.predicateTraversals = new ArrayList<>(); + P.collectTraversals(this.predicate, this.predicateTraversals); + for (final Traversal.Admin t : this.predicateTraversals) { + this.integrateChild(t); + } } private void configurePredicates(final P predicate) { if (predicate instanceof ConnectiveP) ((ConnectiveP) 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); @@ -82,6 +90,9 @@ private boolean setPredicateValues(final P predicate, final Traverser.Ad return false; } + return true; + } else if (predicate.hasTraversal()) { + // Already resolved by P.resolve() — skip, consuming no selectKey entry return true; } else { final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, selectKeysIterator.next(), traverser), this.traversalRing.next()); @@ -112,14 +123,31 @@ public void removeStartKey() { @Override protected boolean filter(final Traverser.Admin traverser) { + // Resolve the left-hand value (current traverser or startKey scope value) 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()); - final boolean predicateValuesProductive = this.setPredicateValues(this.predicate, traverser, this.selectKeys.iterator()); - this.traversalRing.reset(); + if (!product.isProductive()) { + this.traversalRing.reset(); + return false; + } + + if (this.predicate.hasTraversal()) { + // Resolve traversal-bearing predicates first + this.predicate.resolve(traverser); + } - return product.isProductive() && predicateValuesProductive && this.predicate.test(product.get()); + // Resolve scope-label children (setPredicateValues skips traversal-bearing leaves) + if (!this.selectKeys.isEmpty()) { + final boolean predicateValuesProductive = this.setPredicateValues(this.predicate, traverser, this.selectKeys.iterator()); + this.traversalRing.reset(); + if (!predicateValuesProductive) return false; + } else { + this.traversalRing.reset(); + } + + return this.predicate.test(product.get()); } @Override @@ -136,7 +164,7 @@ public Set getScopeKeys() { public HashSet getPopInstructions() { final HashSet popInstructions = new HashSet<>(); popInstructions.addAll(Scoping.super.getPopInstructions()); - popInstructions.addAll(TraversalParent.super.getPopInstructions()); + popInstructions.addAll(ReadOnlyTraversalParent.super.getPopInstructions()); return popInstructions; } @@ -145,6 +173,8 @@ public WherePredicateStep clone() { final WherePredicateStep clone = (WherePredicateStep) super.clone(); clone.predicate = this.predicate.clone(); clone.traversalRing = this.traversalRing.clone(); + clone.predicateTraversals = new ArrayList<>(); + P.collectTraversals(clone.predicate, clone.predicateTraversals); return clone; } @@ -152,6 +182,7 @@ public WherePredicateStep clone() { public void setTraversal(final Traversal.Admin parentTraversal) { super.setTraversal(parentTraversal); this.traversalRing.getTraversals().forEach(this::integrateChild); + this.predicateTraversals.forEach(this::integrateChild); } @Override @@ -166,7 +197,12 @@ public Set getRequirements() { @Override public List> getLocalChildren() { - return (List) this.traversalRing.getTraversals(); + if (this.predicateTraversals.isEmpty()) { + return (List) this.traversalRing.getTraversals(); + } + final List> children = new ArrayList<>((List) this.traversalRing.getTraversals()); + children.addAll((List) this.predicateTraversals); + return children; } @Override diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java index 830fef2c80e..46658205827 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java @@ -363,6 +363,7 @@ public AbstractAddElementStepPlaceholder clone() { clone.properties = new HashMap<>(); for (Map.Entry> entry : this.properties.entrySet()) { final Object key = entry.getKey(); + final Object clonedKey = key instanceof Traversal ? ((Traversal) key).asAdmin().clone() : key; final List oldValues = entry.getValue(); final List newValues = new ArrayList<>(oldValues.size()); for (Object v : oldValues) { @@ -374,7 +375,7 @@ public AbstractAddElementStepPlaceholder clone() { newValues.add(v); } } - clone.properties.put(key, newValues); + clone.properties.put(clonedKey, newValues); } clone.scopeKeys = new HashSet<>(this.scopeKeys); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FormatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FormatStep.java index 00aaa376280..82ce5f31386 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FormatStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FormatStep.java @@ -150,7 +150,7 @@ public FormatStep clone() { final FormatStep clone = (FormatStep) super.clone(); clone.format = this.format; clone.variables = this.variables; - clone.traversalRing = this.traversalRing; + clone.traversalRing = this.traversalRing.clone(); return clone; } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java index 7e64cd391a5..8d47673b1ac 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java @@ -24,11 +24,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep; import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters; import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException; +import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Element; import org.apache.tinkerpop.gremlin.structure.T; @@ -37,10 +39,12 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Objects; import java.util.function.Supplier; @@ -48,7 +52,7 @@ * @author Marko A. Rodriguez (http://markorodriguez.com) * @author Pieter Martin */ -public class GraphStep extends AbstractStep implements GraphStepContract { +public class GraphStep extends AbstractStep implements GraphStepContract, ReadOnlyTraversalParent { protected Parameters parameters = new Parameters(); protected final Class returnClass; @@ -58,6 +62,7 @@ public class GraphStep extends AbstractStep implemen protected boolean done = false; private Traverser.Admin head = null; private Iterator iterator = EmptyIterator.instance(); + private Traversal.Admin idTraversal; public GraphStep(final Traversal.Admin traversal, final Class returnClass, final boolean isStart, final Object... ids) { @@ -76,7 +81,36 @@ public GraphStep(final Traversal.Admin traversal, final Class returnClass, fi this.getTraversal().getGraph().get().edges(this.ids)); } + public GraphStep(final Traversal.Admin traversal, final Class returnClass, final boolean isStart, final Traversal.Admin idTraversal) { + this(traversal, returnClass, isStart); + this.idTraversal = idTraversal; + if (this.idTraversal != null) { + this.integrateChild(this.idTraversal); + } + } + + /** + * Returns the child traversal used to resolve element IDs, or {@code null} if literal IDs are used. + */ + public Traversal.Admin getIdTraversal() { + return this.idTraversal; + } + + /** + * Sets the child traversal used to resolve element IDs. Calls {@link #integrateChild(Traversal.Admin)} + * on the provided traversal. + */ + public void setIdTraversal(final Traversal.Admin idTraversal) { + this.idTraversal = idTraversal; + if (this.idTraversal != null) { + this.integrateChild(this.idTraversal); + } + } + public String toString() { + if (this.idTraversal != null) { + return StringFactory.stepString(this, this.returnClass.getSimpleName().toLowerCase(), this.idTraversal); + } return StringFactory.stepString(this, this.returnClass.getSimpleName().toLowerCase(), Arrays.toString(this.ids)); } @@ -164,16 +198,65 @@ protected Traverser.Admin processNextStart() { if (this.isStart) { if (this.done) throw FastNoSuchElementException.instance(); - else { + if (this.idTraversal != null) { + // Start step with idTraversal: generate a synthetic traverser to seed + // the child traversal, consistent with how mergeV/addV handle start steps. + this.done = true; + final Traverser.Admin syntheticTraverser = (Traverser.Admin) + this.getTraversal().getTraverserGenerator().generate(false, (Step) this, 1L); + final Object[] resolvedIds = resolveTraversalIds(syntheticTraverser); + this.iterator = lookupElements(resolvedIds); + } else { this.done = true; this.iterator = null == this.iteratorSupplier ? EmptyIterator.instance() : this.iteratorSupplier.get(); } } else { this.head = this.starts.next(); - this.iterator = null == this.iteratorSupplier ? EmptyIterator.instance() : this.iteratorSupplier.get(); + if (this.idTraversal != null) { + final Object[] resolvedIds = resolveTraversalIds(this.head); + this.iterator = lookupElements(resolvedIds); + } else { + this.iterator = null == this.iteratorSupplier ? EmptyIterator.instance() : this.iteratorSupplier.get(); + } + } + } + } + } + + /** + * Resolves element IDs by evaluating the child traversal against the current traverser. + * Handles Element (extract ID), Collection (unpack), and raw values. + */ + @SuppressWarnings("unchecked") + private Object[] resolveTraversalIds(final Traverser.Admin traverser) { + final List ids = new ArrayList<>(); + TraversalUtil.prepare(traverser, (Traversal.Admin) this.idTraversal); + while (this.idTraversal.hasNext()) { + final Object result = this.idTraversal.next(); + if (result instanceof Element) { + ids.add(((Element) result).id()); + } else if (result instanceof Collection) { + for (final Object item : (Collection) result) { + ids.add(item instanceof Element ? ((Element) item).id() : item); } + } else { + ids.add(result); } } + return ids.toArray(); + } + + /** + * Looks up elements (vertices or edges) by the given IDs using the graph. + */ + @SuppressWarnings("unchecked") + private Iterator lookupElements(final Object[] elementIds) { + if (elementIds.length == 0) { + return EmptyIterator.instance(); + } + return (Iterator) (Vertex.class.isAssignableFrom(this.returnClass) ? + this.getTraversal().getGraph().get().vertices(elementIds) : + this.getTraversal().getGraph().get().edges(elementIds)); } @Override @@ -182,6 +265,9 @@ public void reset() { this.head = null; this.done = false; this.iterator = EmptyIterator.instance(); + if (this.idTraversal != null) { + this.idTraversal.reset(); + } } @Override @@ -195,6 +281,31 @@ public int hashCode() { return result; } + @SuppressWarnings("unchecked") + @Override + public List> getLocalChildren() { + return this.idTraversal != null + ? Collections.singletonList((Traversal.Admin) this.idTraversal) + : Collections.emptyList(); + } + + @Override + public GraphStep clone() { + final GraphStep clone = (GraphStep) super.clone(); + if (this.idTraversal != null) { + clone.idTraversal = this.idTraversal.clone(); + } + return clone; + } + + @Override + public void setTraversal(final Traversal.Admin parentTraversal) { + super.setTraversal(parentTraversal); + if (this.idTraversal != null) { + this.integrateChild(this.idTraversal); + } + } + /** * Attempts to close an underlying iterator if it is of type {@link CloseableIterator}. Graph providers may choose * to return this interface containing their vertices and edges if there are expensive resources that might need to @@ -203,6 +314,11 @@ public int hashCode() { @Override public void close() { CloseableIterator.closeIterator(iterator); + try { + ReadOnlyTraversalParent.super.close(); + } catch (final Exception e) { + throw new RuntimeException(e); + } } /** @@ -213,6 +329,7 @@ public void close() { * @return true if the {@link HasContainer} updated ids and thus, was processed. */ public static boolean processHasContainerIds(final GraphStep graphStep, final HasContainer hasContainer) { + if (hasContainer.hasTraversal()) return false; final String key = hasContainer.getKey(); if (key != null && key.equals(T.id.getAccessor()) && graphStep.ids.length == 0 && (hasContainer.getBiPredicate() == Compare.eq || hasContainer.getBiPredicate() == Contains.within)) { diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java index 4223f98bd5c..0901a671962 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java @@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.*; import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; +import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Element; import org.apache.tinkerpop.gremlin.structure.Property; @@ -35,6 +36,7 @@ import org.apache.tinkerpop.gremlin.structure.util.keyed.KeyedProperty; import org.apache.tinkerpop.gremlin.structure.util.keyed.KeyedVertexProperty; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -50,12 +52,22 @@ public class AddPropertyStep extends SideEffectStep implem private Parameters internalParameters = new Parameters(); private Parameters withConfiguration = new Parameters(); private final VertexProperty.Cardinality cardinality; + /** + * Marks the single-argument {@code property(traversal)} form whose child traversal must produce a Map of + * property key/value pairs. Dispatch is driven by this flag rather than by inspecting the property key. + */ + private final boolean mapForm; private CallbackRegistry callbackRegistry; public AddPropertyStep(final Traversal.Admin traversal, final VertexProperty.Cardinality cardinality, final Object keyObject, final Object valueObject) { + this(traversal, cardinality, keyObject, valueObject, false); + } + + public AddPropertyStep(final Traversal.Admin traversal, final VertexProperty.Cardinality cardinality, final Object keyObject, final Object valueObject, final boolean mapForm) { super(traversal); this.internalParameters.set(this, T.key, keyObject, T.value, valueObject); this.cardinality = cardinality; + this.mapForm = mapForm; } @Override @@ -89,11 +101,109 @@ protected void sideEffect(final Traverser.Admin traverser) { throw new IllegalStateException(String.format("T.%s is immutable on existing elements", ((T) k).name())); final String key = (String) k; - final Object value = this.internalParameters.get(traverser, T.value, () -> { - throw new IllegalStateException("The AddPropertyStep does not have a provided value: " + this); - }).get(0); + + // Check if the raw value is a traversal to enable multi-result handling. + // Exclude ConstantTraversal which is used internally by TinkerPop to wrap literal values. + final List rawValues = this.internalParameters.get(T.value, null); + final boolean valueIsTraversal = !rawValues.isEmpty() + && rawValues.get(0) instanceof Traversal.Admin + && !(rawValues.get(0) instanceof ConstantTraversal); + + if (valueIsTraversal) { + handleTraversalValue(traverser, key); + } else { + final Object value = this.internalParameters.get(traverser, T.value, () -> { + throw new IllegalStateException("The AddPropertyStep does not have a provided value: " + this); + }).get(0); + final Object[] vertexPropertyKeyValues = this.internalParameters.getKeyValues(traverser, T.key, T.value); + applyPropertyMutation(traverser, key, value, vertexPropertyKeyValues); + } + } + + /** + * Handles the case where the value argument is a child traversal, supporting multi-result + * resolution, Map-producing traversals, and cardinality-aware property setting. + */ + private void handleTraversalValue(final Traverser.Admin traverser, final String key) { + final List rawValues = this.internalParameters.get(T.value, null); + final Traversal.Admin valueTraversal = (Traversal.Admin) rawValues.get(0); + + // Collect all results from the child traversal + final List results = new ArrayList<>(); + final Traverser.Admin trav = traverser; + final Iterator itty = TraversalUtil.applyAll(trav, (Traversal.Admin) (Traversal.Admin) valueTraversal); + while (itty.hasNext()) { + results.add(itty.next()); + } + + // No-result case: skip mutation, pass element through unchanged + if (results.isEmpty()) { + return; + } + + final Element element = traverser.get(); final Object[] vertexPropertyKeyValues = this.internalParameters.getKeyValues(traverser, T.key, T.value); + // Map-producing form: single-argument property(traversal) where the traversal produces a Map. + // Only the dedicated map form expands a Map into per-entry properties; for the key+traversal form a + // Map result is treated as an ordinary property value. + if (this.mapForm) { + if (results.size() == 1 && results.get(0) instanceof Map) { + final Map map = (Map) results.get(0); + for (final Map.Entry entry : map.entrySet()) { + if (!(entry.getKey() instanceof String)) { + throw new IllegalArgumentException( + "Property key must be a String but found " + entry.getKey().getClass().getSimpleName()); + } + final String mapKey = (String) entry.getKey(); + applyPropertyMutation(traverser, mapKey, entry.getValue(), vertexPropertyKeyValues); + } + return; + } + + // The map form requires a Map result. Reject anything else rather than guessing. + final Object result = results.get(0); + throw new IllegalArgumentException( + "property(traversal) requires the traversal to produce a Map, but got: " + + (result == null ? "null" : result.getClass().getSimpleName())); + } + + // Multi-result handling with cardinality awareness + if (results.size() > 1) { + // Determine effective cardinality + final VertexProperty.Cardinality effectiveCard = this.cardinality != null + ? this.cardinality + : (element instanceof Vertex ? element.graph().features().vertex().getCardinality(key) : null); + + if (effectiveCard == VertexProperty.Cardinality.single) { + throw new IllegalArgumentException( + "Single-cardinality property requires exactly one value, but traversal produced " + + results.size() + " results"); + } + + // For list/set cardinality with multiple results, add each as a separate property value + if (effectiveCard == VertexProperty.Cardinality.list || effectiveCard == VertexProperty.Cardinality.set) { + if (!(element instanceof Vertex)) { + throw new IllegalStateException(String.format( + "Property cardinality can only be set for a Vertex but the traversal encountered %s for key: %s", + element.getClass().getSimpleName(), key)); + } + for (final Object v : results) { + applyPropertyMutation(traverser, key, v, vertexPropertyKeyValues); + } + return; + } + } + + // Single result or default cardinality: use the first result + applyPropertyMutation(traverser, key, results.get(0), vertexPropertyKeyValues); + } + + /** + * Applies a single property mutation to the element, handling eventing and cardinality. + */ + private void applyPropertyMutation(final Traverser.Admin traverser, final String key, + final Object value, final Object[] vertexPropertyKeyValues) { final Element element = traverser.get(); // can't set cardinality if the element is something other than a vertex as only vertices can have @@ -116,7 +226,7 @@ protected void sideEffect(final Traverser.Admin traverser) { final VertexProperty.Cardinality card = this.cardinality != null ? this.cardinality - : element.graph().features().vertex().getCardinality(key); + : (element instanceof Vertex ? element.graph().features().vertex().getCardinality(key) : null); // update property if (element instanceof Vertex) { @@ -183,7 +293,7 @@ public CallbackRegistry getMutatingCallbackRe @Override public int hashCode() { - final int hash = super.hashCode() ^ this.internalParameters.hashCode() ^ this.withConfiguration.hashCode(); + int hash = super.hashCode() ^ this.internalParameters.hashCode() ^ this.withConfiguration.hashCode() ^ Boolean.hashCode(this.mapForm); return (null != this.cardinality) ? (hash ^ cardinality.hashCode()) : hash; } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepContract.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepContract.java index c6547ad425d..cd7da9b6fda 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepContract.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepContract.java @@ -19,11 +19,11 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect; import org.apache.tinkerpop.gremlin.process.traversal.Step; +import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring; import org.apache.tinkerpop.gremlin.process.traversal.step.Deleting; import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping; -import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.Writing; import org.apache.tinkerpop.gremlin.process.traversal.step.PropertiesHolder; import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.Event; @@ -32,8 +32,9 @@ import java.util.HashSet; import java.util.List; -public interface AddPropertyStepContract extends Step, TraversalParent, Scoping, PropertiesHolder, - Writing, Deleting, Configuring { +public interface AddPropertyStepContract extends Step, Scoping, PropertiesHolder, + Writing, Deleting, Configuring, + ReadOnlyTraversalParent { /** * Concrete implementations of this contract that can be referenced as TinkerPop implementations. @@ -46,7 +47,7 @@ public interface AddPropertyStepContract extends Step, TraversalParent, default HashSet getPopInstructions() { final HashSet popInstructions = new HashSet<>(); popInstructions.addAll(Scoping.super.getPopInstructions()); - popInstructions.addAll(TraversalParent.super.getPopInstructions()); + popInstructions.addAll(ReadOnlyTraversalParent.super.getPopInstructions()); return popInstructions; } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepPlaceholder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepPlaceholder.java index 3bb1c087cfc..2ab0e2f0c0d 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepPlaceholder.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepPlaceholder.java @@ -62,8 +62,18 @@ public class AddPropertyStepPlaceholder extends SideEffectSte private Parameters withConfiguration = new Parameters(); + /** + * Marks the single-argument {@code property(traversal)} (Map-producing) form. + */ + private boolean mapForm; + public AddPropertyStepPlaceholder(final Traversal.Admin traversal, final VertexProperty.Cardinality cardinality, final Object keyObject, final Object valueObject) { + this(traversal, cardinality, keyObject, valueObject, false); + } + + public AddPropertyStepPlaceholder(final Traversal.Admin traversal, final VertexProperty.Cardinality cardinality, final Object keyObject, final Object valueObject, final boolean mapForm) { super(traversal); + this.mapForm = mapForm; if (keyObject instanceof GValue) { throw new IllegalArgumentException("GValue is not allowed for property keys"); } @@ -128,13 +138,14 @@ public boolean equals(Object o) { return Objects.equals(key, that.key) && Objects.equals(value, that.value) && cardinality == that.cardinality && + mapForm == that.mapForm && Objects.equals(properties, that.properties) && Objects.equals(withConfiguration, that.withConfiguration); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), key, value, cardinality, properties, withConfiguration); + return Objects.hash(super.hashCode(), key, value, cardinality, mapForm, properties, withConfiguration); } @Override @@ -176,6 +187,7 @@ public Object getValueWithGValue() { public AddPropertyStepPlaceholder clone() { final AddPropertyStepPlaceholder clone = (AddPropertyStepPlaceholder) super.clone(); clone.cardinality = cardinality; + clone.mapForm = mapForm; // Attempt to deep clone key for Traversal and GValue. Shallow copy is fine if key is a String or enum if (this.key instanceof Traversal) { @@ -199,6 +211,7 @@ public AddPropertyStepPlaceholder clone() { clone.properties = new HashMap<>(); for (Map.Entry> entry : this.properties.entrySet()) { final Object key = entry.getKey(); + final Object clonedKey = key instanceof Traversal ? ((Traversal) key).asAdmin().clone() : key; final List oldValues = entry.getValue(); final List newValues = new ArrayList<>(oldValues.size()); for (Object v : oldValues) { @@ -210,7 +223,7 @@ public AddPropertyStepPlaceholder clone() { newValues.add(v); } } - clone.properties.put(key, newValues); + clone.properties.put(clonedKey, newValues); } return clone; @@ -218,7 +231,7 @@ public AddPropertyStepPlaceholder clone() { @Override public AddPropertyStep asConcreteStep() { - AddPropertyStep step = new AddPropertyStep<>(traversal, cardinality, key, value instanceof GValue ? ((GValue) value).get() : value); + AddPropertyStep step = new AddPropertyStep<>(traversal, cardinality, key, value instanceof GValue ? ((GValue) value).get() : value, mapForm); for (final Map.Entry> entry : properties.entrySet()) { for (Object value : entry.getValue()) { diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java index 99a9c4e959d..82204d49f29 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java @@ -119,7 +119,7 @@ public HasContainer clone() { @Override public int hashCode() { - return (this.key != null ? this.key.hashCode() : 0) ^ (this.predicate != null ? this.predicate.hashCode() : 0); + return (this.key != null ? this.key.hashCode() : 0) ^ this.predicate.hashCode(); } public final String getKey() { @@ -142,6 +142,14 @@ public final Object getValue() { return this.predicate.getValue(); } + /** + * Determines if this {@code HasContainer}'s predicate holds a child traversal whose result is resolved + * at runtime (e.g. {@code P.eq(traversal)} or {@code P.within(traversal)}). + */ + public boolean hasTraversal() { + return this.predicate.hasTraversal(); + } + //////////// /** diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java index 8a6edcde280..b3e5b57a46f 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java @@ -62,6 +62,10 @@ * pure filters with inlining reduces the number of variations of a filter that a graph provider may need to reason * about when writing their own strategies. As a result, this strategy helps increase the likelihood that a provider's * filtering optimization will succeed at re-writing the traversal. + *

+ * Has-steps containing traversal-bearing predicates (i.e. {@code has("age", P.gt(__.V(1).values("age")))}) are + * excluded from inlining because their child traversals must be resolved per-traverser at runtime and cannot be + * safely merged with adjacent has-steps or folded into edge labels. * * @author Marko A. Rodriguez (http://markorodriguez.com) * @example

@@ -114,6 +118,14 @@ step instanceof OrStep && processOrStep((OrStep) step, traversal) ||
     ///////////////////////////
 
     private static boolean processHasStep(final HasStep step, final Traversal.Admin traversal) {
+        // Skip inlining for has-steps with traversal-bearing predicates. These contain child traversals that
+        // must be resolved per-traverser at runtime and cannot be merged into adjacent steps.
+        if (step.getHasContainers().stream().anyMatch(HasContainer::hasTraversal)) return false;
+        if (step.getPreviousStep() instanceof HasStep) {
+            // Also skip if the previous has-step contains traversal-bearing predicates, since merging into
+            // it would mix static and dynamic predicates in a single step.
+            if (((HasStep) step.getPreviousStep()).getHasContainers().stream().anyMatch(HasContainer::hasTraversal)) return false;
+        }
         if (step.getPreviousStep() instanceof HasStep) {
             final HasStep previousStep = (HasStep) step.getPreviousStep();
             final List hasContainers = new ArrayList<>(step.getHasContainers());
@@ -221,6 +233,11 @@ private static boolean processOrStep(final OrStep step, final Traversal.Admin
             InlineFilterStrategy.instance().apply(childTraversal);
             for (final Step childStep : childTraversal.getSteps()) {
                 if (childStep instanceof HasStep) {
+                    // Skip optimization if any HasContainer has a traversal-bearing predicate
+                    if (((HasStep) childStep).getHasContainers().stream().anyMatch(HasContainer::hasTraversal)) {
+                        process = false;
+                        break;
+                    }
                     P p = null;
                     for (final HasContainer hasContainer : ((HasStep) childStep).getHasContainers()) {
                         if (null == key)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java
index 4354fac80db..1369fac3dd7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/StandardVerificationStrategy.java
@@ -23,6 +23,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ReadOnlyTraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DiscardStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
@@ -32,6 +33,7 @@
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.RequirementsStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.SupplyingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.ReadOnlyChildValidator;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 
@@ -76,6 +78,23 @@ public void apply(final Traversal.Admin traversal) {
             if (step instanceof RepeatStep && null == ((RepeatStep) step).getRepeatTraversal())
                 throw new VerificationException("The repeat()-traversal was not defined:" + traversal, traversal);
 
+            if (step instanceof ReadOnlyTraversalParent) {
+                for (final Traversal.Admin child : ((ReadOnlyTraversalParent) step).getLocalChildren()) {
+                    try {
+                        ReadOnlyChildValidator.validate(child);
+                    } catch (final IllegalArgumentException e) {
+                        throw new VerificationException(e.getMessage(), traversal);
+                    }
+                }
+                for (final Traversal.Admin child : ((ReadOnlyTraversalParent) step).getGlobalChildren()) {
+                    try {
+                        ReadOnlyChildValidator.validate(child);
+                    } catch (final IllegalArgumentException e) {
+                        throw new VerificationException(e.getMessage(), traversal);
+                    }
+                }
+            }
+
         }
 
         // The ProfileSideEffectStep must be one of the following
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java
index db5cced9ecf..1275e08f04c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java
@@ -20,6 +20,7 @@
 
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.PBiPredicate;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.io.Serializable;
@@ -56,6 +57,34 @@ public P negate() {
         return new OrP<>(this.predicates);
     }
 
+    /**
+     * Resolves child predicates with short-circuiting. Because a conjunction fails as soon as any child
+     * predicate cannot be satisfied, resolution stops at the first child that resolves empty (i.e. a scalar
+     * predicate whose child traversal produced no comparison value). This avoids evaluating the remaining
+     * child traversals, which may be expensive. Collection predicates (within/without) never resolve empty
+     * (they resolve to an empty collection), so they do not trigger the short-circuit.
+     */
+    @Override
+    public void resolve(final Traverser.Admin traverser) {
+        // No super.resolve(): a connective predicate carries no child traversal of its own; only its
+        // operands do. Resolving each operand directly is sufficient (and enables the short-circuit below).
+        for (final P p : this.predicates) {
+            if (p.hasTraversal()) {
+                p.resolve(traverser);
+                if (p.isResolvedEmpty()) return;
+            }
+        }
+    }
+
+    @Override
+    public boolean isResolvedEmpty() {
+        // AND short-circuits: if any child resolved empty, the conjunction cannot be satisfied
+        for (final P p : this.predicates) {
+            if (p.hasTraversal() && p.isResolvedEmpty()) return true;
+        }
+        return false;
+    }
+
     @Override
     public String toString() {
         return "and(" + StringFactory.removeEndBrackets(this.predicates) + ")";
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java
index ef5a1142c31..fa277d2806c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.process.traversal.util;
 
 import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 
 import java.util.ArrayList;
@@ -134,4 +135,21 @@ public Set> getGValues() {
         }
         return allGValues;
     }
+
+    @Override
+    public boolean hasTraversal() {
+        if (super.hasTraversal()) return true;
+        for (final P p : this.predicates) {
+            if (p.hasTraversal()) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void resolve(final Traverser.Admin traverser) {
+        super.resolve(traverser);
+        for (final P p : this.predicates) {
+            p.resolve(traverser);
+        }
+    }
 }
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java
index 2a0c27c7af2..0a054033e99 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java
@@ -57,6 +57,19 @@ public P negate() {
         return new AndP<>(this.predicates);
     }
 
+    @Override
+    public boolean isResolvedEmpty() {
+        // OR short-circuits: only empty if ALL traversal-bearing children resolved empty
+        boolean anyTraversal = false;
+        for (final P p : this.predicates) {
+            if (p.hasTraversal()) {
+                anyTraversal = true;
+                if (!p.isResolvedEmpty()) return false;
+            }
+        }
+        return anyTraversal;
+    }
+
     @Override
     public String toString() {
         return "or(" + StringFactory.removeEndBrackets(this.predicates) + ")";
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReadOnlyChildValidator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReadOnlyChildValidator.java
new file mode 100644
index 00000000000..9bff213c246
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReadOnlyChildValidator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+
+import java.util.List;
+
+/**
+ * Validates that child traversals do not contain mutating steps. Child traversals used as
+ * arguments to filter predicates ({@code has()}, {@code is()}, etc.), lookup steps
+ * ({@code V(traversal)}, {@code E(traversal)}), and mutation steps ({@code property(traversal)})
+ * must be read-only - their purpose is to compute values, not produce side effects.
+ */
+public final class ReadOnlyChildValidator {
+
+    private ReadOnlyChildValidator() {
+    }
+
+    /**
+     * Validates that a child traversal contains no {@link Mutating} steps at any nesting depth.
+     * Throws {@link IllegalArgumentException} if one is found.
+     */
+    public static void validate(final Traversal.Admin child) {
+        final List mutatingSteps = TraversalHelper.getStepsOfAssignableClassRecursively(Mutating.class, child);
+        if (!mutatingSteps.isEmpty()) {
+            final Step found = (Step) mutatingSteps.get(0);
+            throw new IllegalArgumentException(String.format(
+                    "Child traversal contains a mutating step '%s' in '%s'. " +
+                    "Mutating steps are not allowed in child traversals.",
+                    found.getClass().getSimpleName(),
+                    child));
+        }
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java
index e26a621ba00..cd16ef308c4 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java
@@ -96,7 +96,7 @@ public void shouldParseVariableWithNoOp() {
                 VariableResolver.NullVariableResolver.instance());
         final GraphTraversal t = (GraphTraversal) GremlinQueryParser.parse("g.V().has('name',gt(z))", gremlinAntlrToJava);
 
-        assertEquals(g.V().has("name", P.gt(null)).asAdmin().getGremlinLang(),
+        assertEquals(g.V().has("name", P.gt((Object) null)).asAdmin().getGremlinLang(),
                 t.asAdmin().getGremlinLang());
     }
 
@@ -107,7 +107,7 @@ public void shouldParseMultiVariablesWithNoOp() {
                 VariableResolver.NullVariableResolver.instance());
         final GraphTraversal t = (GraphTraversal) GremlinQueryParser.parse("g.V(a,b,c).has('name',gt(z))", gremlinAntlrToJava);
 
-        assertEquals(g.V(null, null, null).has("name", P.gt(null)).asAdmin().getGremlinLang(),
+        assertEquals(g.V(null, null, null).has("name", P.gt((Object) null)).asAdmin().getGremlinLang(),
                 t.asAdmin().getGremlinLang());
     }
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTraversalTest.java
new file mode 100644
index 00000000000..12e0ab78ec1
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTraversalTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.language.grammar;
+
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that the Gremlin grammar correctly parses the new traversal-accepting syntax forms
+ * for has(), V(), E(), property(), and predicates.
+ */
+public class GremlinQueryParserTraversalTest {
+
+    private GraphTraversalSource g;
+    private GremlinAntlrToJava antlrToLanguage;
+
+    @Before
+    public void setup() {
+        g = traversal().withEmbedded(EmptyGraph.instance());
+        antlrToLanguage = new GremlinAntlrToJava();
+    }
+
+    private Object eval(final String query) {
+        final GremlinLexer lexer = new GremlinLexer(CharStreams.fromString(query));
+        final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer));
+        return antlrToLanguage.visit(parser.queryList());
+    }
+
+    private void compare(final Object expected, final Object actual) {
+        assertEquals(((DefaultGraphTraversal) expected).asAdmin().getGremlinLang(),
+                ((DefaultGraphTraversal) actual).asAdmin().getGremlinLang());
+    }
+
+    // ---- has(key, traversal) ----
+
+    @Test
+    public void shouldParseHasStringTraversal() {
+        compare(g.V().has("name", __.values("x")),
+                eval("g.V().has('name', __.values('x'))"));
+    }
+
+    // ---- has(label, key, traversal) ----
+
+    @Test
+    public void shouldParseHasStringStringTraversal() {
+        compare(g.V().has("person", "name", __.values("x")),
+                eval("g.V().has('person', 'name', __.values('x'))"));
+    }
+
+    // ---- has(T, traversal) ----
+
+    @Test
+    public void shouldParseHasTTraversal() {
+        compare(g.V().has(T.id, __.values("x")),
+                eval("g.V().has(T.id, __.values('x'))"));
+    }
+
+    // ---- V(traversal) mid-traversal ----
+
+    @Test
+    public void shouldParseVTraversalMidTraversal() {
+        compare(g.V().out().V(__.select("ids")),
+                eval("g.V().out().V(__.select('ids'))"));
+    }
+
+    // ---- E(traversal) mid-traversal ----
+
+    @Test
+    public void shouldParseETraversalMidTraversal() {
+        compare(g.V().out().E(__.select("ids")),
+                eval("g.V().out().E(__.select('ids'))"));
+    }
+
+    // ---- property(key, traversal) ----
+
+    @Test
+    public void shouldParsePropertyKeyTraversal() {
+        compare(g.V().property("key", __.select("val")),
+                eval("g.V().property('key', __.select('val'))"));
+    }
+
+    // ---- property(Cardinality, key, traversal) ----
+
+    @Test
+    public void shouldParsePropertyCardinalityKeyTraversal() {
+        compare(g.V().property(VertexProperty.Cardinality.single, "key", __.select("val")),
+                eval("g.V().property(Cardinality.single, 'key', __.select('val'))"));
+    }
+
+    // ---- P.eq(traversal) via has ----
+
+    @Test
+    public void shouldParseHasWithPEqTraversal() {
+        compare(g.V().has("name", P.eq(__.values("x"))),
+                eval("g.V().has('name', P.eq(__.values('x')))"));
+    }
+
+    // ---- P.gt(traversal) via has ----
+
+    @Test
+    public void shouldParseHasWithPGtTraversal() {
+        compare(g.V().has("age", P.gt(__.values("x"))),
+                eval("g.V().has('age', P.gt(__.values('x')))"));
+    }
+
+    // ---- P.within(traversal) via has ----
+
+    @Test
+    public void shouldParseHasWithPWithinTraversal() {
+        compare(g.V().has("name", P.within(__.values("x"))),
+                eval("g.V().has('name', P.within(__.values('x')))"));
+    }
+
+    // ---- property(traversal) - Map-producing form ----
+
+    @Test
+    public void shouldParsePropertyTraversal() {
+        compare(g.V().property(__.V().project("a").by("name")),
+                eval("g.V().property(__.V().project('a').by('name'))"));
+    }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTraversalRoundTripTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTraversalRoundTripTest.java
new file mode 100644
index 00000000000..77915f79e05
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTraversalRoundTripTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.language.grammar.GremlinAntlrToJava;
+import org.apache.tinkerpop.gremlin.language.grammar.GremlinQueryParser;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
+import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Parameterized round-trip test for GremlinLang serialization of traversal-bearing arguments.
+ * Each test case serializes a traversal to GremlinLang, parses it back via the ANTLR grammar,
+ * and verifies the resulting GremlinLang string is structurally identical.
+ * 

+ * This complements the Gherkin feature tests (which verify execution semantics) by ensuring that + * the stringification/parsing layer preserves all traversal argument forms correctly. + */ +@RunWith(Parameterized.class) +public class GremlinLangTraversalRoundTripTest { + + private static final GraphTraversalSource g = traversal().with(EmptyGraph.instance()); + + @Parameterized.Parameter + public Traversal traversal; + + @Parameterized.Parameters(name = "{0}") + public static Iterable data() { + return Arrays.asList(new Object[][]{ + // === has() with traversal values === + {g.V().has("name", __.values("x"))}, + {g.V().has("name", __.constant("marko"))}, + {g.V().has("name", __.V().values("name"))}, + {g.V().has("person", "name", __.values("x"))}, + + // === has() with predicate-wrapped traversals === + {g.V().has("name", P.eq(__.values("x")))}, + {g.V().has("age", P.gt(__.constant(30)))}, + {g.V().has("age", P.lt(__.V().values("age")))}, + {g.V().has("age", P.gte(__.constant(18)))}, + {g.V().has("age", P.lte(__.constant(65)))}, + {g.V().has("age", P.neq(__.constant(0)))}, + + // === ConnectiveP with traversals === + {g.V().has("age", P.gt(__.constant(10)).and(P.lt(__.constant(30))))}, + {g.V().has("age", P.lt(__.constant(20)).or(P.gt(__.constant(50))))}, + {g.V().has("age", P.gt(__.constant(10)).and(P.lt(__.constant(30))).or(P.eq(__.constant(99))))}, + + // === within/without with traversals === + {g.V().has("name", P.within(__.V().values("name").fold()))}, + {g.V().has("name", P.without(__.V().values("name").fold()))}, + {g.V().has("name", P.within(__.constant("a"), __.constant("b")))}, + + // === not() with traversal === + {g.V().has("name", __.not(__.identity()))}, + + // === hasId/hasLabel/hasKey/hasValue with traversals === + {g.V().hasId(__.V().id())}, + {g.V().hasId(P.eq(__.V().id()))}, + {g.V().hasLabel(__.V().label())}, + {g.V().properties("age").hasKey(__.constant("age"))}, + {g.V().properties("age").hasValue(__.constant(29))}, + + // === is() with traversals === + {g.V().values("age").is(__.constant(29))}, + {g.V().values("age").is(P.gt(__.V().values("age")))}, + {g.V().values("age").is(P.within(__.V().values("age").fold()))}, + + // === V() and E() with traversals === + {g.V().V(__.select("ids"))}, + {g.V().V(__.out("knows").id())}, + {g.V().E(__.select("edgeIds"))}, + {g.V().E(__.outE().id())}, + {g.V(__.V().id())}, + {g.E(__.V().outE().id())}, + + // === property() with traversals === + {g.V().property("key", __.select("val"))}, + {g.V().property("key", __.V().values("name"))}, + {g.V().property("count", __.out().count())}, + {g.V().property(Cardinality.list, "x", __.out().values("name"))}, + {g.V().property(__.V().project("a").by("name"))}, + + // === where() with traversal predicates === + {g.V().values("age").where(P.gt(__.V().values("age")))}, + {g.V().values("age").where(P.within(__.V().values("age").fold()))}, + + // === literal arguments === + {g.V().has("name", "marko")}, + {g.V().has("name", P.eq("marko"))}, + {g.V().has("age", P.gt(30))}, + {g.V().has("name", P.within("a", "b", "c"))}, + {g.V(1)}, + {g.V(1, 2, 3)}, + }); + } + + @Test + public void shouldRoundTrip() { + final String originalGremlin = traversal.asAdmin().getGremlinLang().getGremlin(); + final GremlinAntlrToJava antlr = new GremlinAntlrToJava(); + final Object parsed = GremlinQueryParser.parse(originalGremlin, antlr); + final String roundTrippedGremlin = ((Traversal) parsed).asAdmin().getGremlinLang().getGremlin(); + assertEquals("GremlinLang round-trip failed for: " + originalGremlin, + originalGremlin, roundTrippedGremlin); + } +} diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java index 4a8959a1ee1..4cf1ec667d9 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java @@ -20,6 +20,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; +import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser; import org.apache.tinkerpop.gremlin.process.traversal.util.AndP; import org.apache.tinkerpop.gremlin.process.traversal.util.OrP; import org.junit.Before; @@ -65,8 +66,8 @@ public static Iterable data() { {P.eq(-0), +0, true}, {P.eq(0), 1, false}, {P.eq(0), null, false}, - {P.eq(null), null, true}, - {P.eq(null), 0, false}, + {P.eq((Object) null), null, true}, + {P.eq((Object) null), 0, false}, {P.eq(Double.POSITIVE_INFINITY), Double.NEGATIVE_INFINITY, false}, {P.eq(Float.POSITIVE_INFINITY), Float.NEGATIVE_INFINITY, false}, {P.eq(Float.POSITIVE_INFINITY), Double.NEGATIVE_INFINITY, false}, @@ -82,8 +83,8 @@ public static Iterable data() { {P.neq(-0), +0, false}, {P.neq(0), 1, true}, {P.neq(0), null, true}, - {P.neq(null), null, false}, - {P.neq(null), 0, true}, + {P.neq((Object) null), null, false}, + {P.neq((Object) null), 0, true}, {P.neq(Double.POSITIVE_INFINITY), Double.NEGATIVE_INFINITY, true}, {P.neq(Float.POSITIVE_INFINITY), Float.NEGATIVE_INFINITY, true}, {P.neq(Float.POSITIVE_INFINITY), Double.NEGATIVE_INFINITY, true}, @@ -320,6 +321,27 @@ public static Iterable data() { {TextP.regex(GValue.ofString("x", "Tinker.*\\u00A9")), "Apache TinkerPop©", true}, {TextP.notRegex(GValue.ofString("x", "(?i)[a-b]{3}-[1-9]{3}-[a-z]{3}")), "123-ABC-456", true}, {TextP.notRegex(GValue.ofString("x", "Tinker.*\\u00A9")), "Apache TinkerPop©", false}, + // Traversal-bearing predicates (resolved per-traverser before testing) + {P.eq(__.constant(0)), 0, true}, + {P.eq(__.constant(0)), 1, false}, + {P.neq(__.constant(0)), 1, true}, + {P.neq(__.constant(0)), 0, false}, + {P.gt(__.constant(0)), 1, true}, + {P.gt(__.constant(0)), 0, false}, + {P.gt(__.constant(0)), -1, false}, + {P.lt(__.constant(0)), -1, true}, + {P.lt(__.constant(0)), 0, false}, + {P.lt(__.constant(0)), 1, false}, + {P.gte(__.constant(0)), 0, true}, + {P.gte(__.constant(0)), 1, true}, + {P.gte(__.constant(0)), -1, false}, + {P.lte(__.constant(0)), 0, true}, + {P.lte(__.constant(0)), -1, true}, + {P.lte(__.constant(0)), 1, false}, + {P.within(__.inject(1, 2, 3).fold()), 2, true}, + {P.within(__.inject(1, 2, 3).fold()), 5, false}, + {P.without(__.inject(1, 2, 3).fold()), 5, true}, + {P.without(__.inject(1, 2, 3).fold()), 2, false}, })); } @@ -337,6 +359,8 @@ public void shouldTest() { if (expected instanceof Class) exceptionRule.expect((Class) expected); + if (predicate.hasTraversal()) predicate.resolve(new B_O_Traverser<>("test", 1L)); + assertEquals(expected, predicate.test(value)); assertNotEquals(expected, predicate.clone().negate().test(value)); assertNotEquals(expected, P.not(predicate.clone()).test(value)); @@ -349,6 +373,14 @@ public void shouldTest() { @Before public void init() { + // Skip value manipulation tests for traversal-bearing predicates since their + // value is resolved at runtime, not set statically. + if (predicate.hasTraversal()) { + assertNotNull(predicate.hashCode()); + assertEquals(predicate, predicate.clone()); + return; + } + final Object pv = predicate.getValue(); final Random r = new Random(); assertNotNull(predicate.getBiPredicate()); @@ -468,7 +500,7 @@ public void shouldHandleNullValuesForSetValue() { assertTrue(predicate.test(null)); assertFalse(predicate.test(INITIAL_VALUE)); assertEquals("eq", predicate.toString()); - assertEquals(predicate, P.eq(null)); + assertEquals(predicate, P.eq((Object) null)); assertNotEquals(predicate, P.eq(INITIAL_VALUE)); } @@ -504,4 +536,368 @@ public void shouldUseUpdatedValueAfterSetValueContaining() { assertNotEquals(textPredicate, TextP.containing(initial)); } } + + /** + * Tests that traversal detection in predicates is accurate: {@code P.hasTraversal()} returns + * true for traversal-bearing predicates and false for literal/GValue predicates. + */ + public static class TraversalDetectionTest { + + @Test + public void shouldDetectTraversalInComparisonPredicate() { + final P p = P.eq(__.constant(1)); + assertTrue(p.hasTraversal()); + } + + @Test + public void shouldDetectTraversalInCollectionPredicate() { + final P p = P.within(__.constant(1)); + assertTrue(p.hasTraversal()); + } + + @Test + public void shouldNotDetectTraversalInLiteralPredicate() { + final P p = P.eq(1); + assertFalse(p.hasTraversal()); + } + + @Test + public void shouldNotDetectTraversalInGValuePredicate() { + final P p = P.eq(GValue.of("x", 1)); + assertFalse(p.hasTraversal()); + } + + @Test + public void shouldReturnNullTraversalValueForLiteral() { + final P p = P.eq(42); + assertFalse(p.hasTraversal()); + } + } + + /** + * Tests that scalar predicates (eq, neq, gt, lt, gte, lte) take the first result from a + * multi-result child traversal, and that collection predicates (within, without) accept + * multiple results. + */ + public static class TraversalResolutionTest { + + private Traverser.Admin createTraverser(final Object value) { + return new B_O_Traverser<>(value, 1L); + } + + @Test + public void shouldTakeFirstResultForEq() { + final P p = P.eq(__.union(__.constant(1), __.constant(2))); + p.resolve(createTraverser("start")); + assertTrue(p.test(1)); + assertFalse(p.test(2)); + } + + @Test + public void shouldTakeFirstResultForNeq() { + final P p = P.neq(__.union(__.constant(1), __.constant(2))); + p.resolve(createTraverser("start")); + assertFalse(p.test(1)); + assertTrue(p.test(2)); + } + + @Test + public void shouldTakeFirstResultForGt() { + final P p = P.gt(__.union(__.constant(10), __.constant(20))); + p.resolve(createTraverser("start")); + assertTrue(p.test(11)); + assertFalse(p.test(10)); + } + + @Test + public void shouldTakeFirstResultForLt() { + final P p = P.lt(__.union(__.constant(10), __.constant(20))); + p.resolve(createTraverser("start")); + assertTrue(p.test(9)); + assertFalse(p.test(10)); + } + + @Test + public void shouldTakeFirstResultForGte() { + final P p = P.gte(__.union(__.constant(10), __.constant(20))); + p.resolve(createTraverser("start")); + assertTrue(p.test(10)); + assertFalse(p.test(9)); + } + + @Test + public void shouldTakeFirstResultForLte() { + final P p = P.lte(__.union(__.constant(10), __.constant(20))); + p.resolve(createTraverser("start")); + assertTrue(p.test(10)); + assertFalse(p.test(11)); + } + + @Test + public void shouldAcceptMultipleResultsForWithin() { + final P p = P.within(__.inject(1, 2, 3).fold()); + p.resolve(createTraverser("start")); + assertTrue(p.test(1)); + assertTrue(p.test(2)); + assertTrue(p.test(3)); + assertFalse(p.test(4)); + } + + @Test + public void shouldAcceptMultipleResultsForWithout() { + final P p = P.without(__.inject(1, 2, 3).fold()); + p.resolve(createTraverser("start")); + assertFalse(p.test(1)); + assertFalse(p.test(2)); + assertFalse(p.test(3)); + assertTrue(p.test(4)); + } + + @Test + public void shouldUnfoldSingleTraversalCollectionResultForWithin() { + // A single child traversal whose result is a Collection unfolds into the membership set, + // mirroring within(Collection). + final P p = P.within(__.inject(1, 2, 3).fold()); + p.resolve(createTraverser("start")); + assertTrue(p.test(1)); + assertTrue(p.test(3)); + assertFalse(p.test(4)); + } + + @Test + public void shouldNotUnfoldMultiTraversalCollectionResultsForWithin() { + // Multiple child traversals mirror within(v1, v2, ...): each first result is a single membership + // element with no unfolding. A folded list therefore compares as a list, not its elements. + final P p = P.within(__.inject(1, 2).fold(), __.constant(3)); + p.resolve(createTraverser("start")); + assertFalse(p.test(1)); // 1 is inside the list [1,2], but the list is one element (not unfolded) + assertFalse(p.test(2)); + assertTrue(p.test(3)); // 3 was supplied as its own element + } + + @Test + public void shouldTreatMultiTraversalScalarResultsAsElementsForWithin() { + // Multiple traversals producing scalars — each first result is one membership element. + final P p = P.within(__.constant(1), __.constant(2), __.constant(3)); + p.resolve(createTraverser("start")); + assertTrue(p.test(1)); + assertTrue(p.test(2)); + assertTrue(p.test(3)); + assertFalse(p.test(4)); + } + + @Test + public void shouldNotUnfoldMultiTraversalResultsForWithout() { + final P p = P.without(__.inject(1, 2).fold(), __.constant(3)); + p.resolve(createTraverser("start")); + assertTrue(p.test(1)); // not excluded: the exclusion list element is [1,2], not 1 + assertTrue(p.test(2)); + assertFalse(p.test(3)); // excluded + } + + @Test + public void shouldPassWithoutWhenTraversalResolvesEmpty() { + final P p = P.without(__.limit(0)); + p.resolve(createTraverser("anything")); + assertFalse(p.isResolvedEmpty()); + assertTrue(p.test("anything")); + } + + @Test + public void shouldFailWithinWhenTraversalResolvesEmpty() { + final P p = P.within(__.limit(0)); + p.resolve(createTraverser("anything")); + assertFalse(p.isResolvedEmpty()); + assertFalse(p.test("anything")); + } + + @Test + public void shouldRemainResolvedEmptyForScalarPredicateWithEmptyTraversal() { + final P p = P.eq(__.limit(0)); + p.resolve(createTraverser("anything")); + assertTrue(p.isResolvedEmpty()); + } + } + + /** + * Tests for ConnectiveP (and/or) and NotP with traversal-bearing operands, including + * deeply nested combinations and empty-resolution edge cases. + */ + public static class TraversalConnectiveTest { + + private Traverser.Admin createTraverser(final Object value) { + return new B_O_Traverser<>(value, 1L); + } + + @Test + public void shouldResolveAndPWithTraversalOperands() { + final P p = P.gt(__.constant(10)).and(P.lt(__.constant(20))); + p.resolve(createTraverser("start")); + assertTrue(p.test(15)); + assertFalse(p.test(10)); + assertFalse(p.test(25)); + } + + @Test + public void shouldShortCircuitAndPResolveWhenScalarChildEmpty() { + final P p = P.eq(__.limit(0)).and(P.gt(__.constant(5))); + p.resolve(createTraverser("start")); + assertTrue(p.isResolvedEmpty()); + } + + @Test + public void shouldResolveOrPWithTraversalOperands() { + final P p = P.eq(__.constant(1)).or(P.eq(__.constant(2))); + p.resolve(createTraverser("start")); + assertTrue(p.test(1)); + assertTrue(p.test(2)); + assertFalse(p.test(3)); + } + + @Test + public void shouldResolveNestedAndInsideOr() { + final P p = P.gt(__.constant(10)).and(P.lt(__.constant(20))) + .or(P.gt(__.constant(50)).and(P.lt(__.constant(60)))); + p.resolve(createTraverser("x")); + assertTrue(p.test(15)); + assertTrue(p.test(55)); + assertFalse(p.test(25)); + assertFalse(p.test(5)); + } + + @Test + public void shouldResolveNestedOrInsideAnd() { + final P p = P.eq(__.constant(1)).or(P.eq(__.constant(2))) + .and(P.eq(__.constant(2)).or(P.eq(__.constant(3)))); + p.resolve(createTraverser("x")); + assertTrue(p.test(2)); + assertFalse(p.test(1)); + assertFalse(p.test(3)); + } + + @Test + public void shouldResolveDeeplyNestedConnectives() { + final P p = P.gt(__.constant(0)).and(P.lt(__.constant(10))) + .or(P.gt(__.constant(20)) + .and(P.lt(__.constant(30)).or(P.gt(__.constant(90))))); + p.resolve(createTraverser("x")); + assertTrue(p.test(5)); + assertTrue(p.test(25)); + assertTrue(p.test(95)); + assertFalse(p.test(15)); + assertFalse(p.test(50)); + } + + @Test + public void shouldResolveOrWithOneEmptyChild() { + final P p = P.eq(__.limit(0)).or(P.eq(__.constant(42))); + p.resolve(createTraverser("x")); + assertTrue(p.test(42)); + assertFalse(p.test(99)); + } + + @Test + public void shouldResolveNotPWrappingTraversalPredicate() { + final P p = P.eq(__.constant(42)).negate(); + p.resolve(createTraverser("start")); + assertFalse(p.test(42)); + assertTrue(p.test(99)); + } + + @Test + public void shouldProduceConsistentResultsAcrossManySequentialResolves() { + final P p = P.gt(__.constant(10)); + for (int i = 0; i < 1000; i++) { + p.resolve(createTraverser("start" + i)); + assertTrue(p.test(11)); + assertFalse(p.test(5)); + } + } + } + + /** + * Tests for clone() and negate() operations on traversal-bearing predicates. + */ + public static class TraversalCloneAndNegateTest { + + private Traverser.Admin createTraverser(final Object value) { + return new B_O_Traverser<>(value, 1L); + } + + @Test + public void shouldCloneScalarTraversalPredicate() { + final P original = P.gt(__.constant(10)); + final P clone = original.clone(); + assertTrue(clone.hasTraversal()); + clone.resolve(createTraverser("x")); + assertTrue(clone.test(15)); + assertFalse(clone.test(5)); + } + + @Test + public void shouldCloneWithinTraversalPredicate() { + final P original = P.within(__.inject(1, 2, 3).fold()); + final P clone = original.clone(); + assertTrue(clone.hasTraversal()); + clone.resolve(createTraverser("x")); + assertTrue(clone.test(2)); + assertFalse(clone.test(9)); + } + + @Test + public void shouldCloneConnectivePWithTraversals() { + final P original = P.gt(__.constant(10)).and(P.lt(__.constant(20))); + final P clone = original.clone(); + assertTrue(clone.hasTraversal()); + clone.resolve(createTraverser("x")); + assertTrue(clone.test(15)); + assertFalse(clone.test(25)); + } + + @Test + public void shouldCloneIndependentlyFromOriginal() { + final P original = P.eq(__.constant(42)); + final P clone = original.clone(); + clone.resolve(createTraverser("x")); + assertTrue(clone.test(42)); + assertTrue(original.hasTraversal()); + } + + @Test + public void shouldNegateScalarTraversalPredicate() { + final P p = P.gt(__.constant(10)).negate(); + assertTrue(p.hasTraversal()); + p.resolve(createTraverser("x")); + assertTrue(p.test(5)); + assertFalse(p.test(15)); + } + + @Test + public void shouldNegateConnectivePWithTraversals() { + final P p = P.gt(__.constant(10)).and(P.lt(__.constant(20))).negate(); + p.resolve(createTraverser("x")); + assertTrue(p.test(5)); + assertTrue(p.test(25)); + assertFalse(p.test(15)); + } + + @Test + public void shouldCloneThenNegate() { + final P original = P.eq(__.constant(42)); + final P negated = original.clone().negate(); + assertTrue(negated.hasTraversal()); + negated.resolve(createTraverser("x")); + assertFalse(negated.test(42)); + assertTrue(negated.test(99)); + } + + @Test + public void shouldNegateMultiTraversalWithin() { + final P p = P.within(__.inject(1, 2, 3).fold()).negate(); + assertTrue(p.hasTraversal()); + p.resolve(createTraverser("x")); + assertFalse(p.test(1)); + assertTrue(p.test(9)); + } + } } diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java index 0ed9095ca39..e843b29d658 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java @@ -19,6 +19,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step; import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -47,10 +48,16 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AllStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AnyStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep; import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep; import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep; @@ -106,6 +113,7 @@ import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -133,9 +141,18 @@ public static void setupClass() { public Traversal.Admin traversal; @Parameterized.Parameter(value = 2) + /** + * Expected global children before strategy application. If null, pre-strategy assertions are skipped entirely + * (useful for cases where the step under test only exists after strategy folding, e.g. multiple HasContainers + * folded into a single HasStep by InlineFilterStrategy). + */ public List> expectedGlobalChildren; @Parameterized.Parameter(value = 3) + /** + * Expected local children before strategy application. If null, pre-strategy assertions are skipped entirely. + * See {@link #expectedGlobalChildren} for details. + */ public List> expectedLocalChildren; /** @@ -389,6 +406,30 @@ public static Iterable data() { List.of(__.outE(), __.has("age", P.gte(32))), null, null }, + {AllStep.class, + g.V().values("age").fold().all(P.eq(__.constant(29))), + List.of(), + List.of(__.constant(29)), + null, null + }, + {AllStep.class, + g.V().values("age").fold().all(P.within(__.V().values("age").fold(), __.constant(29))), + List.of(), + List.of(__.V().values("age").fold(), __.constant(29)), + null, null + }, + {AnyStep.class, + g.V().values("age").fold().any(P.eq(__.constant(29))), + List.of(), + List.of(__.constant(29)), + null, null + }, + {AnyStep.class, + g.V().values("age").fold().any(P.within(__.V().values("age").fold(), __.constant(29))), + List.of(), + List.of(__.V().values("age").fold(), __.constant(29)), + null, null + }, {OrStep.class, g.V().or(__.outE(), __.has("age", P.gte(32))), List.of(), @@ -539,12 +580,55 @@ public static Iterable data() { List.of(__.constant("key"), __.constant("value")), null, null }, + {GraphStep.class, + g.V(__.constant(1)), + List.of(), + List.of(__.constant(1)), + null, null + }, + {GraphStep.class, + g.E(__.constant(1)), + List.of(), + List.of(__.constant(1)), + null, null + }, + {HasStep.class, + g.V().has("age", P.eq(__.constant(29))), + List.of(), + List.of(__.constant(29)), + null, null + }, + {HasStep.class, + g.V().has("name", P.within(__.V().values("name").fold(), __.constant("marko"))), + List.of(), + List.of(__.V().values("name").fold(), __.constant("marko")), + null, null + }, + {HasStep.class, + g.V().has("age", P.gt(__.constant(27))).has("name", P.eq(__.constant("marko"))), + null, + null, + List.of(), + List.of(__.constant(27), __.constant("marko")) + }, {IntersectStep.class, g.V().fold().intersect(__.constant(List.of(1, 2, 3))), List.of(), List.of(__.constant(List.of(1, 2, 3))), null, null }, + {IsStep.class, + g.V().values("age").is(P.eq(__.constant(29))), + List.of(), + List.of(__.constant(29)), + null, null + }, + {IsStep.class, + g.V().values("age").is(P.within(__.V().values("age").fold(), __.constant(29))), + List.of(), + List.of(__.V().values("age").fold(), __.constant(29)), + null, null + }, {LocalStep.class, g.V().local(__.outE().count()), List.of(), @@ -587,6 +671,18 @@ public static Iterable data() { List.of(__.has("age", P.gt(27))), null, null }, + {NoneStep.class, + g.V().values("age").fold().none(P.eq(__.constant(29))), + List.of(), + List.of(__.constant(29)), + null, null + }, + {NoneStep.class, + g.V().values("age").fold().none(P.within(__.V().values("age").fold(), __.constant(29))), + List.of(), + List.of(__.V().values("age").fold(), __.constant(29)), + null, null + }, {OptionalStep.class, g.V().optional(__.out("knows")), List.of(), @@ -918,6 +1014,12 @@ public static Iterable data() { List.of(__.constant("value")), null, null }, + {WherePredicateStep.class, + g.V().as("a").out().as("b").where("a", P.eq(__.constant("b"))), + List.of(), + List.of(__.constant("b")), + null, null + }, {WhereTraversalStep.class, g.V().as("a").out().as("b").where(__.as("a").out().as("c")), List.of(), @@ -929,24 +1031,54 @@ public static Iterable data() { @Test public void doTest() { - verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(pre-strategy application)"); + if (expectedGlobalChildren != null && expectedLocalChildren != null) { + verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(pre-strategy application)"); - traversal = traversal.clone(); + final List> preCloneGlobal = getChildTraversals(true); + final List> preCloneLocal = getChildTraversals(false); - verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(cloned traversal, pre-strategy application)"); + traversal = traversal.clone(); + + verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(cloned traversal, pre-strategy application)"); + verifyCloneIndependence(preCloneGlobal, getChildTraversals(true), "(cloned traversal, pre-strategy application)"); + verifyCloneIndependence(preCloneLocal, getChildTraversals(false), "(cloned traversal, pre-strategy application)"); + } traversal.getStrategies().addStrategies(GValueReductionStrategy.instance()); traversal.applyStrategies(); - verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren, - postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren, - "(pre-strategy application)"); + final List> expectedPostGlobal = postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren; + final List> expectedPostLocal = postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren; + + verifyExpectedParents(expectedPostGlobal, expectedPostLocal, "(post-strategy application)"); + + final List> preClonePostStratGlobal = getChildTraversals(true); + final List> preClonePostStratLocal = getChildTraversals(false); traversal = traversal.clone(); - verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren, - postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren, - "(cloned traversal, pre-strategy application)"); + verifyExpectedParents(expectedPostGlobal, expectedPostLocal, "(cloned traversal, post-strategy application)"); + verifyCloneIndependence(preClonePostStratGlobal, getChildTraversals(true), "(cloned traversal, post-strategy application)"); + verifyCloneIndependence(preClonePostStratLocal, getChildTraversals(false), "(cloned traversal, post-strategy application)"); + } + + private List> getChildTraversals(boolean global) { + List> steps = TraversalHelper.getStepsOfAssignableClass(stepClass, traversal); + if (steps.size() != 1 || !(steps.get(0) instanceof TraversalParent)) return List.of(); + TraversalParent parent = (TraversalParent) steps.get(0); + return new ArrayList<>(global ? parent.getGlobalChildren() : parent.getLocalChildren()); + } + + private void verifyCloneIndependence(List> originalChildren, List> clonedChildren, String messageSuffix) { + for (Traversal.Admin clonedChild : clonedChildren) { + if (clonedChild instanceof AbstractLambdaTraversal) continue; + for (Traversal.Admin originalChild : originalChildren) { + assertFalse( + String.format("Cloned child traversal %s should be a different instance from original for Traversal [%s] %s", + clonedChild.toString(), traversal, messageSuffix), + clonedChild == originalChild); + } + } } private void verifyExpectedParents(List> expectedGlobalChildren, List> expectedLocalChildren, String messageSuffix) { diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainerTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainerTest.java new file mode 100644 index 00000000000..2a79b5864c3 --- /dev/null +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainerTest.java @@ -0,0 +1,89 @@ +/* + * 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. + */ +package org.apache.tinkerpop.gremlin.process.traversal.step.util; + +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertEquals; + +/** + * Tests for {@link HasContainer}, including traversal-bearing predicates and lifecycle methods. + * A traversal-bearing container holds a {@link P} whose value is resolved at runtime from a child traversal + * (e.g. {@code P.eq(traversal)}); the container exposes this via {@link HasContainer#hasTraversal()}. + */ +public class HasContainerTest { + + @Test + public void shouldReturnFalseForHasTraversalWithLiteralPredicate() { + final HasContainer hc = new HasContainer("name", P.eq("marko")); + assertThat(hc.hasTraversal(), is(false)); + } + + @Test + public void shouldReturnTrueForHasTraversalWithTraversalPredicate() { + final Traversal.Admin traversal = __.identity().asAdmin(); + final HasContainer hc = new HasContainer("name", P.eq(traversal)); + assertThat(hc.hasTraversal(), is(true)); + } + + @Test + public void shouldSetFieldsCorrectlyWithTraversalPredicate() { + final Traversal.Admin traversal = __.identity().asAdmin(); + final HasContainer hc = new HasContainer("age", P.eq(traversal)); + + assertEquals("age", hc.getKey()); + assertThat(hc.getPredicate().getChildTraversals().get(0), is(sameInstance(traversal))); + } + + @Test + public void shouldCloneProduceIndependentDeepCopyOfTraversalPredicate() { + final Traversal.Admin traversal = __.identity().asAdmin(); + final HasContainer original = new HasContainer("name", P.eq(traversal)); + final HasContainer clone = original.clone(); + + // clone's predicate should carry a traversal that is not the same instance + assertThat(clone.getPredicate().getChildTraversals(), is(notNullValue())); + assertThat(clone.getPredicate().getChildTraversals().get(0), + is(not(sameInstance(original.getPredicate().getChildTraversals().get(0))))); + + // key should be equal + assertEquals(original.getKey(), clone.getKey()); + + // both should still report hasTraversal + assertThat(clone.hasTraversal(), is(true)); + } + + @Test + public void shouldCloneLiteralHasContainerWithoutTraversal() { + final HasContainer original = new HasContainer("name", P.eq("marko")); + final HasContainer clone = original.clone(); + + assertThat(clone.hasTraversal(), is(false)); + assertEquals("name", clone.getKey()); + assertEquals(P.eq("marko"), clone.getPredicate()); + } +} diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java index c4c0a44dc6e..02748bdaa68 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java @@ -143,6 +143,13 @@ public static Iterable generateTestParameters() { {outE().hasLabel(P.eq("knows").or(P.gt("created"))).has("weight", gt(1.0)).inV(), addHas(outE(), T.label.getAccessor(), P.eq("knows").or(P.gt("created")), "weight", gt(1.0)).inV(), Collections.emptyList()}, {outE().hasLabel(P.eq("knows").or(P.eq("created"))).has("weight", gt(1.0)).inV(), outE("knows", "created").has("weight", gt(1.0)).inV(), Collections.emptyList()}, {outE().hasLabel(P.within("knows", "created")).inV(), outE("knows", "created").inV(), Collections.emptyList()}, + // + // Traversal-bearing has-steps: a HasStep carrying a traversal predicate is never merged + // with an adjacent HasStep. filter-unwrapping still applies (safe), but and-decomposition + // leaves two separate HasSteps rather than merging them into one. + {has("age", P.gt(__.V().values("age"))).has("name", "marko"), has("age", P.gt(__.V().values("age"))).has("name", "marko"), Collections.emptyList()}, + {filter(has("age", P.gt(__.V().values("age")))), has("age", P.gt(__.V().values("age"))), Collections.emptyList()}, + {and(has("name", "marko"), has("age", P.gt(__.V().values("age")))), addHas(addHas(__.start(), "name", eq("marko")), "age", P.gt(__.V().values("age"))), Collections.emptyList()}, }); } diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReadOnlyChildValidatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReadOnlyChildValidatorTest.java new file mode 100644 index 00000000000..1c796e57b99 --- /dev/null +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReadOnlyChildValidatorTest.java @@ -0,0 +1,261 @@ +/* + * 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. + */ +package org.apache.tinkerpop.gremlin.process.traversal.util; + +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.TextP; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; +import org.junit.Test; + +import static org.junit.Assert.assertThrows; + +/** + * Tests for construction-time child traversal validation. + */ +public class ReadOnlyChildValidatorTest { + + private final GraphTraversalSource g = EmptyGraph.instance().traversal(); + + // ===== FILTER CONTEXT: should reject mutating steps ===== + + @Test + public void shouldRejectAddVInHasTraversal() { + assertThrows(IllegalArgumentException.class, () -> + g.V().has("name", __.addV("x").values("name"))); + } + + @Test + public void shouldRejectDropInHasTraversal() { + assertThrows(IllegalArgumentException.class, () -> + g.V().has("name", __.V().drop().constant("x"))); + } + + @Test + public void shouldRejectNestedMutatingInHasTraversal() { + assertThrows(IllegalArgumentException.class, () -> + g.V().has("name", __.V().map(__.addV("x")).values("name"))); + } + + @Test + public void shouldRejectMutatingInHasWithTAccessor() { + assertThrows(IllegalArgumentException.class, () -> + g.V().has(org.apache.tinkerpop.gremlin.structure.T.label, __.addV("x").label())); + } + + @Test + public void shouldRejectMutatingInHasWithLabel() { + assertThrows(IllegalArgumentException.class, () -> + g.V().has("person", "name", __.addV("x").values("name"))); + } + + // ===== LOOKUP CONTEXT: should reject mutating steps ===== + + @Test + public void shouldRejectAddVInMidTraversalV() { + assertThrows(IllegalArgumentException.class, () -> + g.V().V(__.addV("x").id())); + } + + @Test + public void shouldRejectAddVInMidTraversalE() { + assertThrows(IllegalArgumentException.class, () -> + g.V().E(__.addV("x").id())); + } + + @Test + public void shouldRejectAddVInStartStepV() { + assertThrows(IllegalArgumentException.class, () -> + g.V(__.addV("x").id())); + } + + @Test + public void shouldRejectAddVInStartStepE() { + assertThrows(IllegalArgumentException.class, () -> + g.E(__.addV("x").id())); + } + + // ===== P FACTORY METHODS: should reject mutating steps ===== + + @Test + public void shouldRejectMutatingInPEq() { + assertThrows(IllegalArgumentException.class, () -> + P.eq(__.addV("x").values("name"))); + } + + @Test + public void shouldRejectMutatingInPNeq() { + assertThrows(IllegalArgumentException.class, () -> + P.neq(__.addV("x").values("name"))); + } + + @Test + public void shouldRejectMutatingInPGt() { + assertThrows(IllegalArgumentException.class, () -> + P.gt(__.addV("x").values("age"))); + } + + @Test + public void shouldRejectMutatingInPLt() { + assertThrows(IllegalArgumentException.class, () -> + P.lt(__.addV("x").values("age"))); + } + + @Test + public void shouldRejectMutatingInPGte() { + assertThrows(IllegalArgumentException.class, () -> + P.gte(__.addV("x").values("age"))); + } + + @Test + public void shouldRejectMutatingInPLte() { + assertThrows(IllegalArgumentException.class, () -> + P.lte(__.addV("x").values("age"))); + } + + @Test + public void shouldRejectMutatingInPWithin() { + assertThrows(IllegalArgumentException.class, () -> + P.within(__.addV("x").values("name"))); + } + + @Test + public void shouldRejectMutatingInPWithout() { + assertThrows(IllegalArgumentException.class, () -> + P.without(__.addV("x").values("name"))); + } + + @Test + public void shouldRejectMutatingInMultiTraversalWithin() { + assertThrows(IllegalArgumentException.class, () -> + P.within(__.V().values("name"), __.addV("x").values("name"))); + } + + @Test + public void shouldRejectMutatingInMultiTraversalWithout() { + assertThrows(IllegalArgumentException.class, () -> + P.without(__.V().values("name"), __.addV("x").values("name"))); + } + + // ===== TextP FACTORY METHODS: should reject mutating steps ===== + + @Test + public void shouldRejectMutatingInTextPStartingWith() { + assertThrows(IllegalArgumentException.class, () -> + TextP.startingWith(__.addV("x").values("name"))); + } + + @Test + public void shouldRejectMutatingInTextPContaining() { + assertThrows(IllegalArgumentException.class, () -> + TextP.containing(__.addV("x").values("name"))); + } + + // ===== MUTATION CONTEXT: should reject DropStep but allow other mutations ===== + + @Test + public void shouldRejectDropInPropertyTraversal() { + assertThrows(IllegalArgumentException.class, () -> + g.V().property(__.V().map(__.drop()).project("x").by("name"))); + } + + @Test + public void shouldRejectNestedDropInPropertyTraversal() { + assertThrows(IllegalArgumentException.class, () -> + g.V().property(__.V().union(__.drop(), __.constant("x")).project("k").by())); + } + + // ===== VALID TRAVERSALS: should pass without error ===== + + @Test + public void shouldAllowReadOnlyHasTraversal() { + // Should not throw + g.V().has("name", __.V().values("name")); + } + + @Test + public void shouldAllowNavigationInHasTraversal() { + // Should not throw + g.V().has("name", __.V().out("knows").values("name")); + } + + @Test + public void shouldAllowReadOnlyLookupTraversal() { + // Should not throw + g.V().V(__.out("knows").id()); + } + + @Test + public void shouldAllowReadOnlyStartStepV() { + // Should not throw + g.V(__.V().id()); + } + + @Test + public void shouldAllowReadOnlyPredicate() { + // Should not throw + P.eq(__.V().values("age")); + } + + @Test + public void shouldRejectAddVInMutationContext() { + // addV is blocked in property(traversal) - mutating steps are blocked in child traversals + assertThrows(IllegalArgumentException.class, () -> + g.V().property(__.V().addV("temp").project("k").by("name"))); + } + + @Test + public void shouldAllowReadOnlyPropertyTraversal() { + // Should not throw + g.V().property(__.V().project("name").by("name")); + } + + // ===== CHOOSE CONTEXT: should reject traversal-bearing predicates ===== + + @Test + public void shouldRejectTraversalPredicateInChooseIfThen() { + assertThrows(IllegalArgumentException.class, () -> + g.V().values("age").choose(P.gt(__.V().values("age")), __.constant("older"), __.constant("younger"))); + } + + @Test + public void shouldRejectTraversalPredicateInChooseIfOnly() { + assertThrows(IllegalArgumentException.class, () -> + g.V().values("age").choose(P.gt(__.V().values("age")), __.constant("older"))); + } + + @Test + public void shouldRejectTraversalPredicateInChooseOption() { + assertThrows(IllegalArgumentException.class, () -> + g.V().values("age").choose(__.identity()).option(P.gt(__.V().values("age")), __.constant("older"))); + } + + @Test + public void shouldAllowLiteralPredicateInChoose() { + // Literal predicates should still work + g.V().values("age").choose(P.gt(30), __.constant("older"), __.constant("younger")); + } + + @Test + public void shouldAllowLiteralPredicateInChooseOption() { + // Literal predicates as option keys should still work + g.V().values("age").choose(__.identity()).option(P.gt(30), __.constant("older")); + } +} \ No newline at end of file diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs index 13447b6cf60..07f1f32d83c 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs @@ -1068,6 +1068,15 @@ public GraphTraversal HasKey (P? predicate) return Wrap(this); } + ///

+ /// Adds the hasKey step to this . + /// + public GraphTraversal HasKey (ITraversal traversal) + { + GremlinLang.AddStep("hasKey", traversal); + return Wrap(this); + } + /// /// Adds the hasKey step to this . /// @@ -1096,6 +1105,15 @@ public GraphTraversal HasLabel (P? predicate) return Wrap(this); } + /// + /// Adds the hasLabel step to this . + /// + public GraphTraversal HasLabel (ITraversal traversal) + { + GremlinLang.AddStep("hasLabel", traversal); + return Wrap(this); + } + /// /// Adds the hasLabel step to this . /// @@ -1152,6 +1170,15 @@ public GraphTraversal HasValue (P? predicate) return Wrap(this); } + /// + /// Adds the hasValue step to this . + /// + public GraphTraversal HasValue (ITraversal traversal) + { + GremlinLang.AddStep("hasValue", traversal); + return Wrap(this); + } + /// /// Adds the id step to this . /// @@ -1850,6 +1877,16 @@ public GraphTraversal Property(Cardinality cardinality, IDictionar return Wrap(this); } + /// + /// Adds the property step with a map-producing traversal to this . + /// The traversal must produce a Map whose entries become properties on the element. + /// + public GraphTraversal Property(ITraversal propertyTraversal) + { + GremlinLang.AddStep("property", propertyTraversal); + return Wrap(this); + } + /// /// Adds the propertyMap step to this . diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs index 684a76c2f6f..8bdb2e4c84c 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs @@ -26,6 +26,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Numerics; using System.Reflection; using System.Text; @@ -472,11 +473,21 @@ private string AsString(P p) } else if (p.Value is IList listVal && (p.OperatorName == "within" || p.OperatorName == "without")) { - // within/without with a list value - render as [e1,e2,...] + // within/without with a list value if (listVal.Count == 0) { // empty within() - no brackets } + else if (listVal.Cast().All(v => v is ITraversal)) + { + // All elements are traversals - serialize as comma-separated args (no brackets) + // This matches the server grammar: within(trav1, trav2) via genericArgumentVarargs + for (int i = 0; i < listVal.Count; i++) + { + if (i > 0) sb.Append(','); + sb.Append(ArgAsString(listVal[i])); + } + } else { sb.Append('['); diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs index fe33aec3e88..18f827a7ea1 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs @@ -157,12 +157,22 @@ public static P TypeOf(params object[]? args) public static P Within(params object[]? args) { + if (args is { Length: 1 } && args[0] is ITraversal) + return new P("within", args[0]); + // Multiple traversals - store as list preserving ITraversal type for serializer detection + if (args is { Length: > 1 } && args.All(a => a is ITraversal)) + return new P("within", new List(args)); var x = args is { Length: 1 } && args[0] is ICollection collection ? collection : args; return new P("within", ToGenericList(x)); } public static P Without(params object[]? args) { + if (args is { Length: 1 } && args[0] is ITraversal) + return new P("without", args[0]); + // Multiple traversals - store as list preserving ITraversal type for serializer detection + if (args is { Length: > 1 } && args.All(a => a is ITraversal)) + return new P("without", new List(args)); var x = args is { Length: 1 } && args[0] is ICollection collection ? collection : args; return new P("without", ToGenericList(x)); } diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs index cc94f346819..8b0d81e1344 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs @@ -51,31 +51,61 @@ public static TextP Containing(string value) return new TextP("containing", value); } + public static P Containing(object value) + { + return new P("containing", value); + } + public static TextP EndingWith(string value) { return new TextP("endingWith", value); } + public static P EndingWith(object value) + { + return new P("endingWith", value); + } + public static TextP NotContaining(string value) { return new TextP("notContaining", value); } + public static P NotContaining(object value) + { + return new P("notContaining", value); + } + public static TextP NotEndingWith(string value) { return new TextP("notEndingWith", value); } + public static P NotEndingWith(object value) + { + return new P("notEndingWith", value); + } + public static TextP NotStartingWith(string value) { return new TextP("notStartingWith", value); } + public static P NotStartingWith(object value) + { + return new P("notStartingWith", value); + } + public static TextP StartingWith(string value) { return new TextP("startingWith", value); } + public static P StartingWith(object value) + { + return new P("startingWith", value); + } + public static TextP Regex(string value) { return new TextP("regex", value); diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs index 974521747f4..63603d67e28 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs @@ -738,6 +738,14 @@ public static GraphTraversal HasKey(P? predicate) return new GraphTraversal().HasKey(predicate); } + /// + /// Spawns a and adds the hasKey step to that traversal. + /// + public static GraphTraversal HasKey(ITraversal traversal) + { + return new GraphTraversal().HasKey(traversal); + } + /// /// Spawns a and adds the hasKey step to that traversal. /// @@ -756,6 +764,14 @@ public static GraphTraversal HasLabel(P? predicate) return new GraphTraversal().HasLabel(predicate); } + /// + /// Spawns a and adds the hasLabel step to that traversal. + /// + public static GraphTraversal HasLabel(ITraversal traversal) + { + return new GraphTraversal().HasLabel(traversal); + } + /// /// Spawns a and adds the hasLabel step to that traversal. /// @@ -792,6 +808,14 @@ public static GraphTraversal HasValue(P? predicate) return new GraphTraversal().HasValue(predicate); } + /// + /// Spawns a and adds the hasValue step to that traversal. + /// + public static GraphTraversal HasValue(ITraversal traversal) + { + return new GraphTraversal().HasValue(traversal); + } + /// /// Spawns a and adds the id step to that traversal. /// @@ -1278,6 +1302,15 @@ public static GraphTraversal Property(IDictionary().Property(map); } + /// + /// Spawns a and adds the property step with a + /// map-producing traversal to that traversal. + /// + public static GraphTraversal Property(ITraversal propertyTraversal) + { + return new GraphTraversal().Property(propertyTraversal); + } + /// /// Spawns a and adds the propertyMap step to that traversal. /// diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs index 315b5fb70a3..e6238de9a67 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs @@ -484,6 +484,37 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V().Has(T.Label, "person")}}, {"g_V_hasXlabel_eqXpersonXX", new List, ITraversal>> {(g,p) =>g.V().Has(T.Label, P.Eq("person"))}}, {"g_V_hasXname_nullX", new List, ITraversal>> {(g,p) =>g.V().Has("name", (object) null)}}, + {"g_V_hasXname_constantXmarkoXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.Constant("marko"))}}, + {"g_V_hasXname_VXvid1X_outXknowsX_valuesXnameXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.V(p["vid1"]).Out("knows").Values("name").Order())}}, + {"g_V_hasXname_valuesXnonexistentXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.Values("nonexistent"))}}, + {"g_V_hasXname_notXidentityXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.Not(__.Identity()))}}, + {"g_V_hasXage_gtXconstantX29XXX", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Gt(__.Constant(29)))}}, + {"g_V_hasXage_lteXconstantX27XXX", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Lte(__.Constant(27)))}}, + {"g_V_hasXage_neqXconstantX32XXX", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Neq(__.Constant(32)))}}, + {"g_V_hasXname_eqXconstantXmarkoXXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Eq(__.Constant("marko")))}}, + {"g_V_hasXage_ltXconstantX29XXX", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Lt(__.Constant(29)))}}, + {"g_V_hasXage_gteXconstantX32XXX", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Gte(__.Constant(32)))}}, + {"g_V_hasXage_eqXvaluesXnonexistentXXX", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Eq(__.Values("nonexistent")))}}, + {"g_V_hasXlabel_constantXpersonXX", new List, ITraversal>> {(g,p) =>g.V().Has(T.Label, __.Constant("person"))}}, + {"g_V_hasXperson_name_constantXmarkoXX_age", new List, ITraversal>> {(g,p) =>g.V().Has("person", "name", __.Constant("marko")).Values("age")}}, + {"g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_constantXpeterXX_foldXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Within(__.Union(__.V(p["vid1"]).Out("knows").Values("name"), __.Constant("peter")).Fold()))}}, + {"g_V_hasXname_withinXvaluesXnonexistentX_constantXmarkoXXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Within(__.Values("nonexistent"), __.Constant("marko")))}}, + {"g_V_hasXname_withinXvaluesXnonexistentX_valuesXnonexistent2XXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Within(__.Values("nonexistent"), __.Values("nonexistent2")))}}, + {"g_V_hasXname_withoutXconstantXmarkoX_constantXvadasX_constantXpeterXXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Without(__.Constant("marko"), __.Constant("vadas"), __.Constant("peter")))}}, + {"g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_VXvid3X_outXcreatedX_valuesXnameXX_foldXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Within(__.Union(__.V(p["vid1"]).Out("knows").Values("name"), __.V(p["vid3"]).Out("created").Values("name")).Fold()))}}, + {"g_V_hasLabelXsoftwareX_hasXname_withoutXunionXVXvid1X_outXcreatedX_valuesXnameX_VXvid4X_outXcreatedX_valuesXnameXX_foldXX", new List, ITraversal>> {(g,p) =>g.V().HasLabel("software").Has("name", P.Without(__.Union(__.V(p["vid1"]).Out("created").Values("name"), __.V(p["vid4"]).Out("created").Values("name")).Fold()))}}, + {"g_V_hasLabelXpersonX_valuesXageX_isXwithinXunionXVXvid1X_valuesXageX_V_hasXname_lopX_inXcreatedX_valuesXageXX_foldXX", new List, ITraversal>> {(g,p) =>g.V().HasLabel("person").Values("age").Is(P.Within(__.Union(__.V(p["vid1"]).Values("age"), __.V().Has("name", "lop").In("created").Values("age")).Fold()))}}, + {"g_VXvid1X_outEXknowsX_filterXinV_hasXname_withinXunionXV_hasXname_lopX_inXcreatedX_valuesXnameX_V_hasXname_rippleX_inXcreatedX_valuesXnameXX_foldXXXX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE("knows").Filter(__.InV().Has("name", P.Within(__.Union(__.V().Has("name", "lop").In("created").Values("name"), __.V().Has("name", "ripple").In("created").Values("name")).Fold())))}}, + {"g_V_hasLabelXconstantXpersonXX", new List, ITraversal>> {(g,p) =>g.V().HasLabel(__.Constant("person"))}}, + {"g_V_hasIdXeqXVXvid1X_idXX", new List, ITraversal>> {(g,p) =>g.V().HasId(P.Eq(__.V(p["vid1"]).Id()))}}, + {"g_V_hasIdXVXvid1X_idXX", new List, ITraversal>> {(g,p) =>g.V().HasId(__.V(p["vid1"]).Id())}}, + {"g_V_propertiesXageX_hasKeyXconstantXageXX", new List, ITraversal>> {(g,p) =>g.V().Properties("age").HasKey(__.Constant("age"))}}, + {"g_V_propertiesXageX_hasKeyXeqXconstantXageXXX", new List, ITraversal>> {(g,p) =>g.V().Properties("age").HasKey(P.Eq(__.Constant("age")))}}, + {"g_V_propertiesXageX_hasValueXconstantX29XX", new List, ITraversal>> {(g,p) =>g.V().Properties("age").HasValue(__.Constant(29))}}, + {"g_V_propertiesXageX_hasValueXeqXconstantX29XXX", new List, ITraversal>> {(g,p) =>g.V().Properties("age").HasValue(P.Eq(__.Constant(29)))}}, + {"g_VXvid1X_asXaX_V_hasXage_gtXselectXaX_valuesXageXXX_valuesXnameX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").V().Has("age", P.Gt(__.Select("a").Values("age"))).Values("name")}}, + {"g_withSackX29X_V_hasXage_gtXsackXX_valuesXnameX", new List, ITraversal>> {(g,p) =>g.WithSack(29).V().Has("age", P.Gt(__.Sack())).Values("name")}}, + {"g_V_hasXname_markoX_outEXknowsX_hasXweight_gteXconstantX05XXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", "marko").OutE("knows").Has("weight", P.Gte(__.Constant(0.5)))}}, {"g_V_hasIdXemptyX_count", new List, ITraversal>> {(g,p) =>g.V().HasId(p["xx1"]).Count()}}, {"g_V_hasIdXwithinXemptyXX_count", new List, ITraversal>> {(g,p) =>g.V().HasId(P.Within(new List { })).Count()}}, {"g_V_hasIdXwithoutXemptyXX_count", new List, ITraversal>> {(g,p) =>g.V().HasId(P.Without(new List { })).Count()}}, @@ -543,6 +574,28 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Gte(p["xx1"])).Is(P.Lt(p["xx2"]))}}, {"g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX", new List, ITraversal>> {(g,p) =>g.V().Where(__.In("created").Count().Is(1)).Values("name")}}, {"g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX", new List, ITraversal>> {(g,p) =>g.V().Where(__.In("created").Count().Is(P.Gte(2))).Values("name")}}, + {"g_V_valuesXageX_isXconstantX29XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(__.Constant(29))}}, + {"g_V_valuesXnameX_isXconstantXmarkoXX", new List, ITraversal>> {(g,p) =>g.V().Values("name").Is(__.Constant("marko"))}}, + {"g_V_valuesXageX_isXgtXconstantX29XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Gt(__.Constant(29)))}}, + {"g_V_valuesXageX_isXltXconstantX32XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Lt(__.Constant(32)))}}, + {"g_V_valuesXageX_isXneqXconstantX35XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Neq(__.Constant(35)))}}, + {"g_V_valuesXageX_isXwithinXVXvid1X_outXknowsX_valuesXageXXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Within(__.V(p["vid1"]).Out("knows").Values("age").Fold()))}}, + {"g_V_valuesXageX_isXconstantX99999XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(__.Constant(99999))}}, + {"g_V_hasLabelXpersonX_valuesXageX_chooseXgtXconstantX29XX_olderX", new List, ITraversal>> {(g,p) =>g.V().HasLabel("person").Values("age").Choose(__.Is(P.Gt(__.Constant(29))), __.Constant("older than marko"), __.Constant("not older"))}}, + {"g_V_hasLabelXpersonX_valuesXageX_chooseXgteXmeanAgeX_aboveX", new List, ITraversal>> {(g,p) =>g.V().HasLabel("person").Values("age").Choose(__.Is(P.Gte(__.V().HasLabel("person").Values("age").Mean())), __.Constant("above average"), __.Constant("below average"))}}, + {"g_VXvid1X_outXknowsX_valuesXageX_fold_allXgteXconstantX27XXX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("knows").Values("age").Fold().All(P.Gte(__.Constant(27)))}}, + {"g_VXvid1X_outXknowsX_valuesXageX_fold_allXgtXconstantX27XXX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("knows").Values("age").Fold().All(P.Gt(__.Constant(27)))}}, + {"g_VXvid1X_outXknowsX_valuesXageX_fold_anyXeqXconstantX32XXX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("knows").Values("age").Fold().Any(P.Eq(__.Constant(32)))}}, + {"g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX35XXX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("knows").Values("age").Fold().None(P.Eq(__.Constant(35)))}}, + {"g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX32XXX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("knows").Values("age").Fold().None(P.Eq(__.Constant(32)))}}, + {"g_injectXnullX_isXeqXV9999_valuesXnameXXX", new List, ITraversal>> {(g,p) =>g.Inject(null).Is(P.Eq(__.V(9999).Values("name")))}}, + {"g_injectXmarkoX_isXV9999_valuesXnameXX", new List, ITraversal>> {(g,p) =>g.Inject("marko").Is(__.V(9999).Values("name"))}}, + {"g_injectXmarkoX_chooseXeqXV9999_valuesXnameXX_matched_unmatchedX", new List, ITraversal>> {(g,p) =>g.Inject("marko").Choose(__.Is(P.Eq(__.V(9999).Values("name"))), __.Constant("matched"), __.Constant("unmatched"))}}, + {"g_injectXlistX_noneXeqXV9999_valuesXnameXXX", new List, ITraversal>> {(g,p) =>g.Inject(new List { "marko", "josh" }).None(P.Eq(__.V(9999).Values("name")))}}, + {"g_V_hasXname_eqXV9999_valuesXnameXXX", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Eq(__.V(9999).Values("name")))}}, + {"g_V_valuesXageX_isXwithoutXconstantX29X_constantX32XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Without(__.Constant(29), __.Constant(32)))}}, + {"g_VXvid1X_asXaX_V_valuesXageX_isXgtXselectXaX_valuesXageXXX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").V().Values("age").Is(P.Gt(__.Select("a").Values("age")))}}, + {"g_withSackX30X_V_valuesXageX_isXgtXsackXX", new List, ITraversal>> {(g,p) =>g.WithSack(30).V().Values("age").Is(P.Gt(__.Sack()))}}, {"g_V_valuesXageX_noneXgtX32XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").None(P.Gt(32))}}, {"g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Where(__.Is(P.Gt(33))).Fold().None(P.Lte(33))}}, {"g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Order().By(Order.Desc).Fold().None(P.Lt(10))}}, @@ -715,6 +768,16 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V().Where(__.Values("age").Is(P.Gt(30)))}}, {"g_V_whereXlabel_isXsoftwareXX", new List, ITraversal>> {(g,p) =>g.V().Where(__.Label().Is("software"))}}, {"g_V_whereXlabel_isXpersonXX", new List, ITraversal>> {(g,p) =>g.V().Where(__.Label().Is("person"))}}, + {"g_V_valuesXageX_whereXgtXconstantX29XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Where(P.Gt(__.Constant(29)))}}, + {"g_V_valuesXageX_whereXltXconstantX32XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Where(P.Lt(__.Constant(32)))}}, + {"g_V_valuesXageX_whereXeqXconstantX29XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Where(P.Eq(__.Constant(29)))}}, + {"g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Where(P.Within(__.V(p["vid1"]).Out("knows").Values("age").Fold()))}}, + {"g_V_valuesXnameX_whereXneqXconstantXmarkoXXX", new List, ITraversal>> {(g,p) =>g.V().Values("name").Where(P.Neq(__.Constant("marko")))}}, + {"g_V_valuesXageX_whereXeqXconstantX99999XXX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Where(P.Eq(__.Constant(99999)))}}, + {"g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX", new List, ITraversal>> {(g,p) =>g.V().Where(P.Gt(__.V(p["vid1"]).Values("age"))).By("age").Values("name")}}, + {"g_VX1X_asXaX_V_valuesXageX_whereXgteXconstantX0XX_andXneqXaXXX_byX_byXageX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").V().HasLabel("person").Values("age").Where(P.Gte(__.Constant(0)).And(P.Neq("a"))).By().By("age")}}, + {"g_VX1X_asXaX_V_valuesXageX_whereXneqXaX_andXgtXVXvid1X_valuesXageXXXX_byX_byXageX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").V().HasLabel("person").Values("age").Where(P.Neq("a").And(P.Gt(__.V(p["vid1"]).Values("age")))).By().By("age")}}, + {"g_VX1X_asXaX_V_valuesXageX_whereXeqXVXvid1X_valuesXageXX_orXeqXaXXX_byX_byXageX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").V().HasLabel("person").Values("age").Where(P.Eq(__.V(p["vid1"]).Values("age")).Or(P.Eq("a"))).By().By("age")}}, {"g_withStrategiesXAdjacentToIncidentStrategyX_V", new List, ITraversal>> {(g,p) =>g.WithStrategies(new AdjacentToIncidentStrategy()).V()}}, {"g_withoutStrategiesXAdjacentToIncidentStrategyX_V", new List, ITraversal>> {(g,p) =>g.WithoutStrategies(typeof(AdjacentToIncidentStrategy)).V()}}, {"g_withStrategiesXAdjacentToIncidentStrategyX_V_out_count", new List, ITraversal>> {(g,p) =>g.WithStrategies(new AdjacentToIncidentStrategy()).V().Out().Count()}}, @@ -836,6 +899,23 @@ private static IDictionary, ITraversal>> {(g,p) =>g.WithoutStrategies(typeof(SeedStrategy)).V()}}, {"g_withStrategiesXStandardVerificationStrategyX_V", new List, ITraversal>> {(g,p) =>g.WithStrategies(new StandardVerificationStrategy()).V()}}, {"g_withoutStrategiesXStandardVerificationStrategyX_V", new List, ITraversal>> {(g,p) =>g.WithoutStrategies(typeof(StandardVerificationStrategy)).V()}}, + {"g_V_hasXname_addVXxX_valuesXnameXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.AddV((string) "x").Values("name"))}}, + {"g_V_hasXname_V_drop_constantXxXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.V().Drop().Constant("x"))}}, + {"g_V_hasXname_V_mapXaddVXxXX_valuesXnameXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.V().Map(__.AddV((string) "x")).Values("name"))}}, + {"g_V_hasXname_eqXaddVXxX_valuesXnameXXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Eq(__.AddV((string) "x").Values("name")))}}, + {"g_V_hasXname_withinXaddVXxX_valuesXnameXXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Has("name", P.Within(__.AddV((string) "x").Values("name")))}}, + {"g_V_hasXage_gtXaddVXxX_valuesXageXXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Gt(__.AddV((string) "x").Values("age")))}}, + {"g_V_valuesXageX_isXaddVXxX_valuesXageXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(__.AddV((string) "x").Values("age"))}}, + {"g_V_valuesXageX_isXgtXaddVXxX_valuesXageXXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Gt(__.AddV((string) "x").Values("age")))}}, + {"g_V_VXaddVXxX_idX_rejected", new List, ITraversal>> {(g,p) =>g.V().V(__.AddV((string) "x").Id())}}, + {"g_V_EXaddVXxX_idX_rejected", new List, ITraversal>> {(g,p) =>g.V().E(__.AddV((string) "x").Id())}}, + {"g_VXaddVXxX_idX_rejected", new List, ITraversal>> {(g,p) =>g.V(__.AddV((string) "x").Id())}}, + {"g_EXaddVXxX_idX_rejected", new List, ITraversal>> {(g,p) =>g.E(__.AddV((string) "x").Id())}}, + {"g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Property((ITraversal) __.V().Map(__.Drop()).Project("x").By("name"))}}, + {"g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected", new List, ITraversal>> {(g,p) =>g.V().Property((ITraversal) __.AddV((string) "temp").Project("k").By("name"))}}, + {"g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification", new List, ITraversal>> {(g,p) =>g.V().Has("name", __.V(p["vid1"]).Values("name"))}}, + {"g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification", new List, ITraversal>> {(g,p) =>g.V().Has("age", P.Gt(__.V(p["vid1"]).Values("age")))}}, + {"g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).V(__.Out("knows").Id()).Values("name")}}, {"g_withStrategiesXSubgraphStrategyXsubgraphAXX_V", new List, ITraversal>> {(g,p) =>g.WithStrategies(new SubgraphStrategy(vertices: __.Has("name", P.Within("josh", "lop", "ripple")))).V()}}, {"g_withStrategiesXSubgraphStrategyXsubgraphAXX_E", new List, ITraversal>> {(g,p) =>g.WithStrategies(new SubgraphStrategy(vertices: __.Has("name", P.Within("josh", "lop", "ripple")))).E()}}, {"g_withStrategiesXSubgraphStrategyXsubgraphAXX_VX4X_outE", new List, ITraversal>> {(g,p) =>g.WithStrategies(new SubgraphStrategy(vertices: __.Has("name", P.Within("josh", "lop", "ripple")))).V(p["vid4"]).OutE()}}, @@ -946,9 +1026,9 @@ private static IDictionary, ITraversal>> {(g,p) =>g.AddV().Property(Cardinality.Single, new Dictionary {{ "name", "foo" }, { "age", 42 }}), (g,p) =>g.V().Has("name", "foo")}}, {"g_V_hasXname_fooX_propertyXname_setXbarX_age_43X", new List, ITraversal>> {(g,p) =>g.AddV().Property(Cardinality.Single, "name", "foo").Property("age", 42), (g,p) =>g.V().Has("name", "foo").Property(new Dictionary {{ "name", CardinalityValue.Set("bar") }, { "age", 43 }}), (g,p) =>g.V().Has("name", "foo"), (g,p) =>g.V().Has("name", "bar"), (g,p) =>g.V().Has("age", 43), (g,p) =>g.V().Has("age", 42)}}, {"g_V_hasXname_fooX_propertyXset_name_bar_age_singleX43XX", new List, ITraversal>> {(g,p) =>g.AddV().Property(Cardinality.Single, "name", "foo").Property("age", 42), (g,p) =>g.V().Has("name", "foo").Property(Cardinality.Set, new Dictionary {{ "name", "bar" }, { "age", CardinalityValue.Single(43) }}), (g,p) =>g.V().Has("name", "foo"), (g,p) =>g.V().Has("name", "bar"), (g,p) =>g.V().Has("age", 43), (g,p) =>g.V().Has("age", 42)}}, - {"g_addV_propertyXnullX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property(null), (g,p) =>g.V().HasLabel("person").Values()}}, + {"g_addV_propertyXnullX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property((IDictionary) null), (g,p) =>g.V().HasLabel("person").Values()}}, {"g_addV_propertyXemptyX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property(new Dictionary {}), (g,p) =>g.V().HasLabel("person").Values()}}, - {"g_addV_propertyXset_nullX", new List, ITraversal>> {(g,p) =>g.AddV((string) "foo").Property(Cardinality.Set, null), (g,p) =>g.V().HasLabel("foo").Values()}}, + {"g_addV_propertyXset_nullX", new List, ITraversal>> {(g,p) =>g.AddV((string) "foo").Property(Cardinality.Set, (IDictionary) null), (g,p) =>g.V().HasLabel("foo").Values()}}, {"g_addV_propertyXset_emptyX", new List, ITraversal>> {(g,p) =>g.AddV((string) "foo").Property(Cardinality.Set, new Dictionary {}), (g,p) =>g.V().HasLabel("person").Values()}}, {"g_addVXpersonX_propertyXname_joshX_propertyXage_nullX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "josh").Property("age", null), (g,p) =>g.V().Has("person", "age", (object) null)}}, {"g_addVXpersonX_propertyXname_markoX_propertyXfriendWeight_null_acl_nullX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("friendWeight", null, "acl", null), (g,p) =>g.V().Has("person", "name", "marko").Has("friendWeight", (object) null), (g,p) =>g.V().Has("person", "name", "marko").Properties("friendWeight").Has("acl", (object) null), (g,p) =>g.V().Has("person", "name", "marko").Properties("friendWeight").Count()}}, @@ -1189,6 +1269,10 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE("knows").BothV()}}, {"g_VX1X_outEXknowsX_bothV_name", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE("knows").BothV().Values("name")}}, {"g_V_toEXout_knowsvarX_valuesXweightX", new List, ITraversal>> {(g,p) =>g.V().ToE(Direction.Out, (string) p["xx1"]).Values("weight")}}, + {"g_VXvid1X_EXoutE_idX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).E(__.OutE().Id())}}, + {"g_VXvid1X_outEXknowsX_hasXinV_name_vadasX_id_EXidentityX", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE("knows").Filter(__.InV().Has("name", "vadas")).Id().E(__.Identity())}}, + {"g_injectX9999X_EXidentityX", new List, ITraversal>> {(g,p) =>g.Inject(9999).E(__.Identity())}}, + {"g_EXVXvid1X_outE_idX", new List, ITraversal>> {(g,p) =>g.E(__.V(p["vid1"]).OutE().Id())}}, {"g_VX1X_properties_element", new List, ITraversal>> {(g,p) =>g.V(p["vid2"]).Properties().Element().Limit(1)}}, {"g_V_properties_element", new List, ITraversal>> {(g,p) =>g.V().Properties().Element()}}, {"g_V_propertiesXageX_element", new List, ITraversal>> {(g,p) =>g.V().Properties("age").Element()}}, @@ -1853,6 +1937,12 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V().Out("knows").V().Values("name")}}, {"g_V_hasXname_GarciaX_inXsungByX_asXsongX_V_hasXname_Willie_DixonX_inXwrittenByX_whereXeqXsongXX_name", new List, ITraversal>> {(g,p) =>g.V().Has("artist", "name", "Garcia").In("sungBy").As("song").V().Has("artist", "name", "Willie_Dixon").In("writtenBy").Where(P.Eq("song")).Values("name")}}, {"g_V_hasLabelXpersonX_asXpX_VXsoftwareX_addInEXuses_pX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).As("vadas").AddV((string) "software").Property("name", "lop").Property("lang", "java").As("lop").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "software").Property("name", "ripple").Property("lang", "java").As("ripple").AddV((string) "person").Property("name", "peter").Property("age", 35).As("peter").AddE((string) "knows").From("marko").To("vadas").Property("weight", 0.5d).AddE((string) "knows").From("marko").To("josh").Property("weight", 1.0d).AddE((string) "created").From("marko").To("lop").Property("weight", 0.4d).AddE((string) "created").From("josh").To("ripple").Property("weight", 1.0d).AddE((string) "created").From("josh").To("lop").Property("weight", 0.4d).AddE((string) "created").From("peter").To("lop").Property("weight", 0.2d), (g,p) =>g.V().HasLabel("person").As("p").V(p["xx1"]).AddE((string) "uses").From("p"), (g,p) =>g.E().HasLabel("uses"), (g,p) =>g.V(p["vid1"]).OutE("uses"), (g,p) =>g.V(p["vid2"]).OutE("uses"), (g,p) =>g.V(p["vid3"]).InE("uses"), (g,p) =>g.V(p["vid4"]).OutE("uses"), (g,p) =>g.V(p["vid5"]).InE("uses"), (g,p) =>g.V(p["vid6"]).OutE("uses")}}, + {"g_VXvid1X_id_VXidentityX_name", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).Id().V(__.Identity()).Values("name")}}, + {"g_VXvid1_vid2X_id_VXidentityX_name", new List, ITraversal>> {(g,p) =>g.V(p["vid1"], p["vid2"]).Id().V(__.Identity()).Values("name")}}, + {"g_VXvid1X_id_asXbookmarkX_V_hasXname_joshX_VXselectXbookmarkXX_name", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).Id().As("bookmark").V().Has("name", "josh").V(__.Select("bookmark")).Values("name")}}, + {"g_VXvid1X_VXoutXknowsX_idX_name", new List, ITraversal>> {(g,p) =>g.V(p["vid1"]).V(__.Out("knows").Id()).Values("name")}}, + {"g_injectX9999X_VXidentityX", new List, ITraversal>> {(g,p) =>g.Inject(9999).V(__.Identity())}}, + {"g_VXVXvid1X_idX_name", new List, ITraversal>> {(g,p) =>g.V(__.V(p["vid1"]).Id()).Values("name")}}, {"InjectXnullX_eqXnullX", new List, ITraversal>> {(g,p) =>g.Inject(null).Is(P.Eq(null))}}, {"InjectXnullX_neqXnullX", new List, ITraversal>> {(g,p) =>g.Inject(null).Is(P.Neq(null))}}, {"InjectXnullX_ltXnullX", new List, ITraversal>> {(g,p) =>g.Inject(null).Is(P.Lt(null))}}, @@ -2125,6 +2215,16 @@ private static IDictionary, ITraversal>> {(g,p) =>g.Inject(new List { 1, 3, 100, 300 })}}, {"g_injectX1_3_100_300X_set", new List, ITraversal>> {(g,p) =>g.Inject(new HashSet { 1, 3, 100, 300 })}}, {"g_injectX1_1X_set", new List, ITraversal>> {(g,p) =>g.Inject(new HashSet { 1, 1 })}}, + {"g_VXvid2X_propertyXalias_VXvid1X_valuesXnameXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).AddV((string) "person").Property("name", "vadas").Property("age", 27).AddV((string) "software").Property("name", "lop").Property("lang", "java").AddV((string) "person").Property("name", "josh").Property("age", 32).AddV((string) "person").Property("name", "peter").Property("age", 35).AddV((string) "software").Property("name", "ripple").Property("lang", "java"), (g,p) =>g.V(p["vid2"]).Property("alias", __.V(p["vid1"]).Values("name")), (g,p) =>g.V().Has("alias", "marko")}}, + {"g_VXvid1X_propertyXcreatorCount_VXvid1X_inXcreatedX_countX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).AddV((string) "software").Property("name", "lop").Property("lang", "java").As("lop").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "person").Property("name", "peter").Property("age", 35).As("peter").AddV((string) "software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE((string) "knows").From("marko").To(__.V().Has("name", "vadas")).AddE((string) "knows").From("marko").To("josh").AddE((string) "created").From("marko").To("lop").AddE((string) "created").From("josh").To("lop").AddE((string) "created").From("josh").To("ripple").AddE((string) "created").From("peter").To("lop"), (g,p) =>g.V(p["vid1"]).Property("creatorCount", __.V(p["vid1"]).In("created").Count()), (g,p) =>g.V().Has("creatorCount", 3l)}}, + {"g_VXvid1X_propertyXknownCount_outXknowsX_countX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).As("vadas").AddV((string) "software").Property("name", "lop").Property("lang", "java").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "person").Property("name", "peter").Property("age", 35).AddV((string) "software").Property("name", "ripple").Property("lang", "java").AddE((string) "knows").From("marko").To("vadas").AddE((string) "knows").From("marko").To("josh"), (g,p) =>g.V(p["vid1"]).Property("knownCount", __.Out("knows").Count()), (g,p) =>g.V().Has("knownCount", 2l)}}, + {"g_VXvid1X_propertyXcreator_inXcreatedX_valuesXnameXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).AddV((string) "software").Property("name", "lop").Property("lang", "java").As("lop").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "person").Property("name", "peter").Property("age", 35).As("peter").AddV((string) "software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE((string) "knows").From("marko").To(__.V().Has("name", "vadas")).AddE((string) "knows").From("marko").To("josh").AddE((string) "created").From("marko").To("lop").AddE((string) "created").From("josh").To("lop").AddE((string) "created").From("josh").To("ripple").AddE((string) "created").From("peter").To("lop"), (g,p) =>g.V(p["vid1"]).Property("creator", __.In("created").Values("name")), (g,p) =>g.V().Has("creator")}}, + {"g_VXvid2X_propertyXVXvid1X_projectXfriendCount_softwareCreatedXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).As("vadas").AddV((string) "software").Property("name", "lop").Property("lang", "java").As("lop").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "person").Property("name", "peter").Property("age", 35).As("peter").AddV((string) "software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE((string) "knows").From("marko").To("vadas").AddE((string) "knows").From("marko").To("josh").AddE((string) "created").From("marko").To("lop").AddE((string) "created").From("josh").To("lop").AddE((string) "created").From("josh").To("ripple").AddE((string) "created").From("peter").To("lop"), (g,p) =>g.V(p["vid2"]).Property((ITraversal) __.V(p["vid1"]).Project("friendCount", "softwareCreated").By(__.Out("knows").Count()).By(__.Out("created").Values("name"))), (g,p) =>g.V().Has("friendCount", 2l), (g,p) =>g.V().Has("softwareCreated", "lop")}}, + {"g_VXvid2X_propertyXVXvid1X_projectXoriginalName_originalLabelX_byXnameX_byXlabelXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).AddV((string) "software").Property("name", "lop").Property("lang", "java").As("lop").AddV((string) "person").Property("name", "josh").Property("age", 32).AddV((string) "person").Property("name", "peter").Property("age", 35).AddV((string) "software").Property("name", "ripple").Property("lang", "java"), (g,p) =>g.V(p["vid2"]).Property((ITraversal) __.V(p["vid1"]).Project("originalName", "originalLabel").By(__.Values("name")).By(__.Label())), (g,p) =>g.V(p["vid2"]).Has("originalName", "marko"), (g,p) =>g.V(p["vid2"]).Has("originalLabel", "person")}}, + {"g_VXvid1X_propertyXlist_friends_outXknowsX_valuesXnameXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).As("vadas").AddV((string) "software").Property("name", "lop").Property("lang", "java").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "person").Property("name", "peter").Property("age", 35).AddV((string) "software").Property("name", "ripple").Property("lang", "java").AddE((string) "knows").From("marko").To("vadas").AddE((string) "knows").From("marko").To("josh"), (g,p) =>g.V(p["vid1"]).Property(Cardinality.List, "friends", __.Out("knows").Values("name")), (g,p) =>g.V(p["vid1"]).Properties("friends")}}, + {"g_VXvid1X_propertyXset_langs_outXcreatedX_valuesXlangXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).AddV((string) "person").Property("name", "vadas").Property("age", 27).AddV((string) "software").Property("name", "lop").Property("lang", "java").As("lop").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "person").Property("name", "peter").Property("age", 35).AddV((string) "software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE((string) "created").From("josh").To("lop").AddE((string) "created").From("josh").To("ripple"), (g,p) =>g.V(p["vid1"]).Property(Cardinality.Set, "langs", __.Out("created").Values("lang")), (g,p) =>g.V(p["vid1"]).Properties("langs")}}, + {"g_VXvid1X_propertyXsingle_friend_outXknowsX_valuesXnameXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29).As("marko").AddV((string) "person").Property("name", "vadas").Property("age", 27).As("vadas").AddV((string) "software").Property("name", "lop").Property("lang", "java").AddV((string) "person").Property("name", "josh").Property("age", 32).As("josh").AddV((string) "person").Property("name", "peter").Property("age", 35).AddV((string) "software").Property("name", "ripple").Property("lang", "java").AddE((string) "knows").From("marko").To("vadas").AddE((string) "knows").From("marko").To("josh"), (g,p) =>g.V(p["vid1"]).Property(Cardinality.Single, "friend", __.Out("knows").Values("name"))}}, + {"g_VXvid1X_propertyXVXvid1X_groupX_byXidX_byXvaluesXnameXXX", new List, ITraversal>> {(g,p) =>g.AddV((string) "person").Property("name", "marko").Property("age", 29), (g,p) =>g.V(p["vid1"]).Property((ITraversal) __.V(p["vid1"]).Group().By(__.Id()).By(__.Values("name")))}}, {"g_io_readXkryoX", new List, ITraversal>> {(g,p) =>g.Io("data/tinkerpop-modern.kryo").Read(), (g,p) =>g.V(), (g,p) =>g.E()}}, {"g_io_read_withXreader_gryoX", new List, ITraversal>> {(g,p) =>g.Io("data/tinkerpop-modern.kryo").With(IO.Reader, IO.Gryo).Read(), (g,p) =>g.V(), (g,p) =>g.E()}}, {"g_io_readXgraphsonX", new List, ITraversal>> {(g,p) =>g.Io("data/tinkerpop-modern.json").Read(), (g,p) =>g.V(), (g,p) =>g.E()}}, diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go index 343500fa13e..82f5ff777b9 100644 --- a/gremlin-go/driver/cucumber/gremlin.go +++ b/gremlin-go/driver/cucumber/gremlin.go @@ -454,6 +454,37 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_V_hasXlabel_personX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, "person")}}, "g_V_hasXlabel_eqXpersonXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, gremlingo.P.Eq("person"))}}, "g_V_hasXname_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", nil)}}, + "g_V_hasXname_constantXmarkoXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.Constant("marko"))}}, + "g_V_hasXname_VXvid1X_outXknowsX_valuesXnameXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.V(p["vid1"]).Out("knows").Values("name").Order())}}, + "g_V_hasXname_valuesXnonexistentXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.Values("nonexistent"))}}, + "g_V_hasXname_notXidentityXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.Not(gremlingo.T__.Identity()))}}, + "g_V_hasXage_gtXconstantX29XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Gt(gremlingo.T__.Constant(29)))}}, + "g_V_hasXage_lteXconstantX27XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Lte(gremlingo.T__.Constant(27)))}}, + "g_V_hasXage_neqXconstantX32XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Neq(gremlingo.T__.Constant(32)))}}, + "g_V_hasXname_eqXconstantXmarkoXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Eq(gremlingo.T__.Constant("marko")))}}, + "g_V_hasXage_ltXconstantX29XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Lt(gremlingo.T__.Constant(29)))}}, + "g_V_hasXage_gteXconstantX32XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Gte(gremlingo.T__.Constant(32)))}}, + "g_V_hasXage_eqXvaluesXnonexistentXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Eq(gremlingo.T__.Values("nonexistent")))}}, + "g_V_hasXlabel_constantXpersonXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, gremlingo.T__.Constant("person"))}}, + "g_V_hasXperson_name_constantXmarkoXX_age": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", gremlingo.T__.Constant("marko")).Values("age")}}, + "g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_constantXpeterXX_foldXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V(p["vid1"]).Out("knows").Values("name"), gremlingo.T__.Constant("peter")).Fold()))}}, + "g_V_hasXname_withinXvaluesXnonexistentX_constantXmarkoXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Within(gremlingo.T__.Values("nonexistent"), gremlingo.T__.Constant("marko")))}}, + "g_V_hasXname_withinXvaluesXnonexistentX_valuesXnonexistent2XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Within(gremlingo.T__.Values("nonexistent"), gremlingo.T__.Values("nonexistent2")))}}, + "g_V_hasXname_withoutXconstantXmarkoX_constantXvadasX_constantXpeterXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Without(gremlingo.T__.Constant("marko"), gremlingo.T__.Constant("vadas"), gremlingo.T__.Constant("peter")))}}, + "g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_VXvid3X_outXcreatedX_valuesXnameXX_foldXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V(p["vid1"]).Out("knows").Values("name"), gremlingo.T__.V(p["vid3"]).Out("created").Values("name")).Fold()))}}, + "g_V_hasLabelXsoftwareX_hasXname_withoutXunionXVXvid1X_outXcreatedX_valuesXnameX_VXvid4X_outXcreatedX_valuesXnameXX_foldXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("software").Has("name", gremlingo.P.Without(gremlingo.T__.Union(gremlingo.T__.V(p["vid1"]).Out("created").Values("name"), gremlingo.T__.V(p["vid4"]).Out("created").Values("name")).Fold()))}}, + "g_V_hasLabelXpersonX_valuesXageX_isXwithinXunionXVXvid1X_valuesXageX_V_hasXname_lopX_inXcreatedX_valuesXageXX_foldXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Values("age").Is(gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V(p["vid1"]).Values("age"), gremlingo.T__.V().Has("name", "lop").In("created").Values("age")).Fold()))}}, + "g_VXvid1X_outEXknowsX_filterXinV_hasXname_withinXunionXV_hasXname_lopX_inXcreatedX_valuesXnameX_V_hasXname_rippleX_inXcreatedX_valuesXnameXX_foldXXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).OutE("knows").Filter(gremlingo.T__.InV().Has("name", gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V().Has("name", "lop").In("created").Values("name"), gremlingo.T__.V().Has("name", "ripple").In("created").Values("name")).Fold())))}}, + "g_V_hasLabelXconstantXpersonXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel(gremlingo.T__.Constant("person"))}}, + "g_V_hasIdXeqXVXvid1X_idXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(gremlingo.P.Eq(gremlingo.T__.V(p["vid1"]).Id()))}}, + "g_V_hasIdXVXvid1X_idXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(gremlingo.T__.V(p["vid1"]).Id())}}, + "g_V_propertiesXageX_hasKeyXconstantXageXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("age").HasKey(gremlingo.T__.Constant("age"))}}, + "g_V_propertiesXageX_hasKeyXeqXconstantXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("age").HasKey(gremlingo.P.Eq(gremlingo.T__.Constant("age")))}}, + "g_V_propertiesXageX_hasValueXconstantX29XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("age").HasValue(gremlingo.T__.Constant(29))}}, + "g_V_propertiesXageX_hasValueXeqXconstantX29XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("age").HasValue(gremlingo.P.Eq(gremlingo.T__.Constant(29)))}}, + "g_VXvid1X_asXaX_V_hasXage_gtXselectXaX_valuesXageXXX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).As("a").V().Has("age", gremlingo.P.Gt(gremlingo.T__.Select("a").Values("age"))).Values("name")}}, + "g_withSackX29X_V_hasXage_gtXsackXX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSack(29).V().Has("age", gremlingo.P.Gt(gremlingo.T__.Sack())).Values("name")}}, + "g_V_hasXname_markoX_outEXknowsX_hasXweight_gteXconstantX05XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", "marko").OutE("knows").Has("weight", gremlingo.P.Gte(gremlingo.T__.Constant(0.5)))}}, "g_V_hasIdXemptyX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["xx1"]).Count()}}, "g_V_hasIdXwithinXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(gremlingo.P.Within([]interface{}{})).Count()}}, "g_V_hasIdXwithoutXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(gremlingo.P.Without([]interface{}{})).Count()}}, @@ -513,6 +544,28 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_V_valuesXageX_isXgte_29vaarX_isXlt_34varX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Gte(p["xx1"])).Is(gremlingo.P.Lt(p["xx2"]))}}, "g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.In("created").Count().Is(1)).Values("name")}}, "g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.In("created").Count().Is(gremlingo.P.Gte(2))).Values("name")}}, + "g_V_valuesXageX_isXconstantX29XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.T__.Constant(29))}}, + "g_V_valuesXnameX_isXconstantXmarkoXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Is(gremlingo.T__.Constant("marko"))}}, + "g_V_valuesXageX_isXgtXconstantX29XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Gt(gremlingo.T__.Constant(29)))}}, + "g_V_valuesXageX_isXltXconstantX32XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Lt(gremlingo.T__.Constant(32)))}}, + "g_V_valuesXageX_isXneqXconstantX35XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Neq(gremlingo.T__.Constant(35)))}}, + "g_V_valuesXageX_isXwithinXVXvid1X_outXknowsX_valuesXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Within(gremlingo.T__.V(p["vid1"]).Out("knows").Values("age").Fold()))}}, + "g_V_valuesXageX_isXconstantX99999XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.T__.Constant(99999))}}, + "g_V_hasLabelXpersonX_valuesXageX_chooseXgtXconstantX29XX_olderX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Values("age").Choose(gremlingo.T__.Is(gremlingo.P.Gt(gremlingo.T__.Constant(29))), gremlingo.T__.Constant("older than marko"), gremlingo.T__.Constant("not older"))}}, + "g_V_hasLabelXpersonX_valuesXageX_chooseXgteXmeanAgeX_aboveX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Values("age").Choose(gremlingo.T__.Is(gremlingo.P.Gte(gremlingo.T__.V().HasLabel("person").Values("age").Mean())), gremlingo.T__.Constant("above average"), gremlingo.T__.Constant("below average"))}}, + "g_VXvid1X_outXknowsX_valuesXageX_fold_allXgteXconstantX27XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out("knows").Values("age").Fold().All(gremlingo.P.Gte(gremlingo.T__.Constant(27)))}}, + "g_VXvid1X_outXknowsX_valuesXageX_fold_allXgtXconstantX27XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out("knows").Values("age").Fold().All(gremlingo.P.Gt(gremlingo.T__.Constant(27)))}}, + "g_VXvid1X_outXknowsX_valuesXageX_fold_anyXeqXconstantX32XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out("knows").Values("age").Fold().Any(gremlingo.P.Eq(gremlingo.T__.Constant(32)))}}, + "g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX35XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out("knows").Values("age").Fold().None(gremlingo.P.Eq(gremlingo.T__.Constant(35)))}}, + "g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX32XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out("knows").Values("age").Fold().None(gremlingo.P.Eq(gremlingo.T__.Constant(32)))}}, + "g_injectXnullX_isXeqXV9999_valuesXnameXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(nil).Is(gremlingo.P.Eq(gremlingo.T__.V(9999).Values("name")))}}, + "g_injectXmarkoX_isXV9999_valuesXnameXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("marko").Is(gremlingo.T__.V(9999).Values("name"))}}, + "g_injectXmarkoX_chooseXeqXV9999_valuesXnameXX_matched_unmatchedX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("marko").Choose(gremlingo.T__.Is(gremlingo.P.Eq(gremlingo.T__.V(9999).Values("name"))), gremlingo.T__.Constant("matched"), gremlingo.T__.Constant("unmatched"))}}, + "g_injectXlistX_noneXeqXV9999_valuesXnameXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{"marko", "josh"}).None(gremlingo.P.Eq(gremlingo.T__.V(9999).Values("name")))}}, + "g_V_hasXname_eqXV9999_valuesXnameXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Eq(gremlingo.T__.V(9999).Values("name")))}}, + "g_V_valuesXageX_isXwithoutXconstantX29X_constantX32XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Without(gremlingo.T__.Constant(29), gremlingo.T__.Constant(32)))}}, + "g_VXvid1X_asXaX_V_valuesXageX_isXgtXselectXaX_valuesXageXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).As("a").V().Values("age").Is(gremlingo.P.Gt(gremlingo.T__.Select("a").Values("age")))}}, + "g_withSackX30X_V_valuesXageX_isXgtXsackXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSack(30).V().Values("age").Is(gremlingo.P.Gt(gremlingo.T__.Sack()))}}, "g_V_valuesXageX_noneXgtX32XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").None(gremlingo.P.Gt(32))}}, "g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.T__.Is(gremlingo.P.Gt(33))).Fold().None(gremlingo.P.Lte(33))}}, "g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().By(gremlingo.Order.Desc).Fold().None(gremlingo.P.Lt(10))}}, @@ -685,6 +738,16 @@ 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_whereXgtXconstantX29XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Gt(gremlingo.T__.Constant(29)))}}, + "g_V_valuesXageX_whereXltXconstantX32XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Lt(gremlingo.T__.Constant(32)))}}, + "g_V_valuesXageX_whereXeqXconstantX29XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Eq(gremlingo.T__.Constant(29)))}}, + "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").Fold()))}}, + "g_V_valuesXnameX_whereXneqXconstantXmarkoXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Where(gremlingo.P.Neq(gremlingo.T__.Constant("marko")))}}, + "g_V_valuesXageX_whereXeqXconstantX99999XXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.P.Eq(gremlingo.T__.Constant(99999)))}}, + "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_VX1X_asXaX_V_valuesXageX_whereXgteXconstantX0XX_andXneqXaXXX_byX_byXageX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).As("a").V().HasLabel("person").Values("age").Where(gremlingo.P.Gte(gremlingo.T__.Constant(0)).And(gremlingo.P.Neq("a"))).By().By("age")}}, + "g_VX1X_asXaX_V_valuesXageX_whereXneqXaX_andXgtXVXvid1X_valuesXageXXXX_byX_byXageX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).As("a").V().HasLabel("person").Values("age").Where(gremlingo.P.Neq("a").And(gremlingo.P.Gt(gremlingo.T__.V(p["vid1"]).Values("age")))).By().By("age")}}, + "g_VX1X_asXaX_V_valuesXageX_whereXeqXVXvid1X_valuesXageXX_orXeqXaXXX_byX_byXageX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).As("a").V().HasLabel("person").Values("age").Where(gremlingo.P.Eq(gremlingo.T__.V(p["vid1"]).Values("age")).Or(gremlingo.P.Eq("a"))).By().By("age")}}, "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()}}, @@ -806,6 +869,23 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_withoutStrategiesXSeedStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.SeedStrategy()).V()}}, "g_withStrategiesXStandardVerificationStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.StandardVerificationStrategy()).V()}}, "g_withoutStrategiesXStandardVerificationStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.StandardVerificationStrategy()).V()}}, + "g_V_hasXname_addVXxX_valuesXnameXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.AddV("x").Values("name"))}}, + "g_V_hasXname_V_drop_constantXxXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.V().Drop().Constant("x"))}}, + "g_V_hasXname_V_mapXaddVXxXX_valuesXnameXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.V().Map(gremlingo.T__.AddV("x")).Values("name"))}}, + "g_V_hasXname_eqXaddVXxX_valuesXnameXXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Eq(gremlingo.T__.AddV("x").Values("name")))}}, + "g_V_hasXname_withinXaddVXxX_valuesXnameXXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.P.Within(gremlingo.T__.AddV("x").Values("name")))}}, + "g_V_hasXage_gtXaddVXxX_valuesXageXXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Gt(gremlingo.T__.AddV("x").Values("age")))}}, + "g_V_valuesXageX_isXaddVXxX_valuesXageXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.T__.AddV("x").Values("age"))}}, + "g_V_valuesXageX_isXgtXaddVXxX_valuesXageXXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Gt(gremlingo.T__.AddV("x").Values("age")))}}, + "g_V_VXaddVXxX_idX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().V(gremlingo.T__.AddV("x").Id())}}, + "g_V_EXaddVXxX_idX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().E(gremlingo.T__.AddV("x").Id())}}, + "g_VXaddVXxX_idX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(gremlingo.T__.AddV("x").Id())}}, + "g_EXaddVXxX_idX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(gremlingo.T__.AddV("x").Id())}}, + "g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Property(gremlingo.T__.V().Map(gremlingo.T__.Drop()).Project("x").By("name"))}}, + "g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Property(gremlingo.T__.AddV("temp").Project("k").By("name"))}}, + "g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", gremlingo.T__.V(p["vid1"]).Values("name"))}}, + "g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", gremlingo.P.Gt(gremlingo.T__.V(p["vid1"]).Values("age")))}}, + "g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).V(gremlingo.T__.Out("knows").Id()).Values("name")}}, "g_withStrategiesXSubgraphStrategyXsubgraphAXX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.SubgraphStrategy(gremlingo.SubgraphStrategyConfig{Vertices: gremlingo.T__.Has("name", gremlingo.P.Within("josh", "lop", "ripple"))})).V()}}, "g_withStrategiesXSubgraphStrategyXsubgraphAXX_E": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.SubgraphStrategy(gremlingo.SubgraphStrategyConfig{Vertices: gremlingo.T__.Has("name", gremlingo.P.Within("josh", "lop", "ripple"))})).E()}}, "g_withStrategiesXSubgraphStrategyXsubgraphAXX_VX4X_outE": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.SubgraphStrategy(gremlingo.SubgraphStrategyConfig{Vertices: gremlingo.T__.Has("name", gremlingo.P.Within("josh", "lop", "ripple"))})).V(p["vid4"]).OutE()}}, @@ -1159,6 +1239,10 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_VX1X_outEXknowsX_bothV": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).OutE("knows").BothV()}}, "g_VX1X_outEXknowsX_bothV_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).OutE("knows").BothV().Values("name")}}, "g_V_toEXout_knowsvarX_valuesXweightX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().ToE(gremlingo.Direction.Out, p["xx1"]).Values("weight")}}, + "g_VXvid1X_EXoutE_idX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).E(gremlingo.T__.OutE().Id())}}, + "g_VXvid1X_outEXknowsX_hasXinV_name_vadasX_id_EXidentityX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).OutE("knows").Filter(gremlingo.T__.InV().Has("name", "vadas")).Id().E(gremlingo.T__.Identity())}}, + "g_injectX9999X_EXidentityX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(9999).E(gremlingo.T__.Identity())}}, + "g_EXVXvid1X_outE_idX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(gremlingo.T__.V(p["vid1"]).OutE().Id())}}, "g_VX1X_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid2"]).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()}}, @@ -1823,6 +1907,12 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_V_outXknowsX_V_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out("knows").V().Values("name")}}, "g_V_hasXname_GarciaX_inXsungByX_asXsongX_V_hasXname_Willie_DixonX_inXwrittenByX_whereXeqXsongXX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("artist", "name", "Garcia").In("sungBy").As("song").V().Has("artist", "name", "Willie_Dixon").In("writtenBy").Where(gremlingo.P.Eq("song")).Values("name")}}, "g_V_hasLabelXpersonX_asXpX_VXsoftwareX_addInEXuses_pX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("software").Property("name", "ripple").Property("lang", "java").As("ripple").AddV("person").Property("name", "peter").Property("age", 35).As("peter").AddE("knows").From("marko").To("vadas").Property("weight", 0.5).AddE("knows").From("marko").To("josh").Property("weight", 1.0).AddE("created").From("marko").To("lop").Property("weight", 0.4).AddE("created").From("josh").To("ripple").Property("weight", 1.0).AddE("created").From("josh").To("lop").Property("weight", 0.4).AddE("created").From("peter").To("lop").Property("weight", 0.2)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").As("p").V(p["xx1"]).AddE("uses").From("p")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasLabel("uses")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).OutE("uses")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid2"]).OutE("uses")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid3"]).InE("uses")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid4"]).OutE("uses")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid5"]).InE("uses")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid6"]).OutE("uses")}}, + "g_VXvid1X_id_VXidentityX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Id().V(gremlingo.T__.Identity()).Values("name")}}, + "g_VXvid1_vid2X_id_VXidentityX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"], p["vid2"]).Id().V(gremlingo.T__.Identity()).Values("name")}}, + "g_VXvid1X_id_asXbookmarkX_V_hasXname_joshX_VXselectXbookmarkXX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Id().As("bookmark").V().Has("name", "josh").V(gremlingo.T__.Select("bookmark")).Values("name")}}, + "g_VXvid1X_VXoutXknowsX_idX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).V(gremlingo.T__.Out("knows").Id()).Values("name")}}, + "g_injectX9999X_VXidentityX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(9999).V(gremlingo.T__.Identity())}}, + "g_VXVXvid1X_idX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(gremlingo.T__.V(p["vid1"]).Id()).Values("name")}}, "InjectXnullX_eqXnullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(nil).Is(gremlingo.P.Eq(nil))}}, "InjectXnullX_neqXnullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(nil).Is(gremlingo.P.Neq(nil))}}, "InjectXnullX_ltXnullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(nil).Is(gremlingo.P.Lt(nil))}}, @@ -2095,6 +2185,16 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_injectX1_3_100_300X_list": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{1, 3, 100, 300})}}, "g_injectX1_3_100_300X_set": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(gremlingo.NewSimpleSet(1, 3, 100, 300))}}, "g_injectX1_1X_set": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(gremlingo.NewSimpleSet(1, 1))}}, + "g_VXvid2X_propertyXalias_VXvid1X_valuesXnameXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).AddV("person").Property("name", "vadas").Property("age", 27).AddV("software").Property("name", "lop").Property("lang", "java").AddV("person").Property("name", "josh").Property("age", 32).AddV("person").Property("name", "peter").Property("age", 35).AddV("software").Property("name", "ripple").Property("lang", "java")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid2"]).Property("alias", gremlingo.T__.V(p["vid1"]).Values("name"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("alias", "marko")}}, + "g_VXvid1X_propertyXcreatorCount_VXvid1X_inXcreatedX_countX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("person").Property("name", "peter").Property("age", 35).As("peter").AddV("software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE("knows").From("marko").To(gremlingo.T__.V().Has("name", "vadas")).AddE("knows").From("marko").To("josh").AddE("created").From("marko").To("lop").AddE("created").From("josh").To("lop").AddE("created").From("josh").To("ripple").AddE("created").From("peter").To("lop")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Property("creatorCount", gremlingo.T__.V(p["vid1"]).In("created").Count())}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("creatorCount", int64(3))}}, + "g_VXvid1X_propertyXknownCount_outXknowsX_countX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("person").Property("name", "peter").Property("age", 35).AddV("software").Property("name", "ripple").Property("lang", "java").AddE("knows").From("marko").To("vadas").AddE("knows").From("marko").To("josh")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Property("knownCount", gremlingo.T__.Out("knows").Count())}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("knownCount", int64(2))}}, + "g_VXvid1X_propertyXcreator_inXcreatedX_valuesXnameXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("person").Property("name", "peter").Property("age", 35).As("peter").AddV("software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE("knows").From("marko").To(gremlingo.T__.V().Has("name", "vadas")).AddE("knows").From("marko").To("josh").AddE("created").From("marko").To("lop").AddE("created").From("josh").To("lop").AddE("created").From("josh").To("ripple").AddE("created").From("peter").To("lop")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Property("creator", gremlingo.T__.In("created").Values("name"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("creator")}}, + "g_VXvid2X_propertyXVXvid1X_projectXfriendCount_softwareCreatedXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("person").Property("name", "peter").Property("age", 35).As("peter").AddV("software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE("knows").From("marko").To("vadas").AddE("knows").From("marko").To("josh").AddE("created").From("marko").To("lop").AddE("created").From("josh").To("lop").AddE("created").From("josh").To("ripple").AddE("created").From("peter").To("lop")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid2"]).Property(gremlingo.T__.V(p["vid1"]).Project("friendCount", "softwareCreated").By(gremlingo.T__.Out("knows").Count()).By(gremlingo.T__.Out("created").Values("name")))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("friendCount", int64(2))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("softwareCreated", "lop")}}, + "g_VXvid2X_propertyXVXvid1X_projectXoriginalName_originalLabelX_byXnameX_byXlabelXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).AddV("person").Property("name", "peter").Property("age", 35).AddV("software").Property("name", "ripple").Property("lang", "java")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid2"]).Property(gremlingo.T__.V(p["vid1"]).Project("originalName", "originalLabel").By(gremlingo.T__.Values("name")).By(gremlingo.T__.Label()))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid2"]).Has("originalName", "marko")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid2"]).Has("originalLabel", "person")}}, + "g_VXvid1X_propertyXlist_friends_outXknowsX_valuesXnameXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("person").Property("name", "peter").Property("age", 35).AddV("software").Property("name", "ripple").Property("lang", "java").AddE("knows").From("marko").To("vadas").AddE("knows").From("marko").To("josh")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Property(gremlingo.Cardinality.List, "friends", gremlingo.T__.Out("knows").Values("name"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Properties("friends")}}, + "g_VXvid1X_propertyXset_langs_outXcreatedX_valuesXlangXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).AddV("person").Property("name", "vadas").Property("age", 27).AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("person").Property("name", "peter").Property("age", 35).AddV("software").Property("name", "ripple").Property("lang", "java").As("ripple").AddE("created").From("josh").To("lop").AddE("created").From("josh").To("ripple")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Property(gremlingo.Cardinality.Set, "langs", gremlingo.T__.Out("created").Values("lang"))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Properties("langs")}}, + "g_VXvid1X_propertyXsingle_friend_outXknowsX_valuesXnameXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("person").Property("name", "peter").Property("age", 35).AddV("software").Property("name", "ripple").Property("lang", "java").AddE("knows").From("marko").To("vadas").AddE("knows").From("marko").To("josh")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Property(gremlingo.Cardinality.Single, "friend", gremlingo.T__.Out("knows").Values("name"))}}, + "g_VXvid1X_propertyXVXvid1X_groupX_byXidX_byXvaluesXnameXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "marko").Property("age", 29)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Property(gremlingo.T__.V(p["vid1"]).Group().By(gremlingo.T__.Id()).By(gremlingo.T__.Values("name")))}}, "g_io_readXkryoX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Io("data/tinkerpop-modern.kryo").Read()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}}, "g_io_read_withXreader_gryoX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Io("data/tinkerpop-modern.kryo").With(gremlingo.IO.Reader, gremlingo.IO.Gryo).Read()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}}, "g_io_readXgraphsonX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Io("data/tinkerpop-modern.json").Read()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V()}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}}, diff --git a/gremlin-go/driver/gremlinlang.go b/gremlin-go/driver/gremlinlang.go index a08c6a7d31c..f070e521cab 100644 --- a/gremlin-go/driver/gremlinlang.go +++ b/gremlin-go/driver/gremlinlang.go @@ -444,7 +444,22 @@ func (gl *GremlinLang) translatePValue(operator string, values []interface{}) (s sb := strings.Builder{} sb.WriteString(operator + "(") - if len(values) > 1 && operator != "between" && operator != "inside" { + // Check if all values are traversals - if so, serialize as comma-separated args (no brackets) + // This matches the server grammar: within(trav1, trav2) via genericArgumentVarargs + allTraversals := len(values) > 1 + if allTraversals { + for _, v := range values { + switch v.(type) { + case *Traversal, Traversal, *GraphTraversal, GraphTraversal: + // ok, it's a traversal + default: + allTraversals = false + break + } + } + } + + if len(values) > 1 && !allTraversals && operator != "between" && operator != "inside" { sb.WriteString("[") } @@ -459,7 +474,7 @@ func (gl *GremlinLang) translatePValue(operator string, values []interface{}) (s } } - if len(values) > 1 && operator != "between" && operator != "inside" { + if len(values) > 1 && !allTraversals && operator != "between" && operator != "inside" { sb.WriteString("]") } sb.WriteString(")") diff --git a/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts b/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts index 8955acc5f45..8f033c1ded4 100644 --- a/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts +++ b/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts @@ -504,7 +504,7 @@ export default class DotNetTranslateVisitor extends TranslateVisitor { this.sb.push(')'); } - // ─── Traversal method overrides — handleGenerics ───────────────────────── + // ─── Traversal method overrides - handleGenerics ───────────────────────── visitTraversalMethod_asString_Scope(ctx: any): void { this.handleGenerics(ctx); } visitTraversalMethod_branch(ctx: any): void { this.handleGenerics(ctx); } @@ -592,7 +592,7 @@ export default class DotNetTranslateVisitor extends TranslateVisitor { visitTraversalMethod_valueMap_boolean_String(ctx: any): void { this.handleGenerics(ctx); } visitTraversalMethod_values(ctx: any): void { this.handleGenerics(ctx); } - // ─── Traversal method overrides — handleLongArguments ──────────────────── + // ─── Traversal method overrides - handleLongArguments ──────────────────── visitTraversalMethod_limit_long(ctx: any): void { this.handleLongArguments(ctx); } visitTraversalMethod_limit_Scope_long(ctx: any): void { this.handleLongArguments(ctx); } @@ -866,6 +866,45 @@ export default class DotNetTranslateVisitor extends TranslateVisitor { // ─── property ──────────────────────────────────────────────────────────── + visitTraversalMethod_property_Object(ctx: any): void { + // Property(null) is ambiguous with Property(ITraversal) - cast null to IDictionary to disambiguate + if (ctx.genericMapNullableArgument().genericMapNullableLiteral() != null && + ctx.genericMapNullableArgument().genericMapNullableLiteral().nullLiteral() != null) { + this.visit(ctx.getChild(0)); + this.sb.push('('); + this.sb.push('(IDictionary) '); + this.visit(ctx.genericMapNullableArgument()); + this.sb.push(')'); + return; + } + this.visitChildren(ctx); + } + + visitTraversalMethod_property_Cardinality_Object(ctx: any): void { + // Property(Cardinality, null) - cast null to IDictionary to disambiguate + if (ctx.genericMapNullableArgument().genericMapNullableLiteral() != null && + ctx.genericMapNullableArgument().genericMapNullableLiteral().nullLiteral() != null) { + this.visit(ctx.getChild(0)); + this.sb.push('('); + this.visit(ctx.traversalCardinality()); + this.sb.push(', '); + this.sb.push('(IDictionary) '); + this.visit(ctx.genericMapNullableArgument()); + this.sb.push(')'); + return; + } + this.visitChildren(ctx); + } + + visitTraversalMethod_property_Traversal(ctx: any): void { + // Property(ITraversal) - cast to ITraversal to disambiguate + this.visit(ctx.getChild(0)); + this.sb.push('('); + this.sb.push('(ITraversal) '); + this.visit(ctx.nestedTraversal()); + this.sb.push(')'); + } + visitTraversalMethod_property_Cardinality_Object_Object_Object(ctx: any): void { if (ctx.genericArgumentVarargs() == null || ctx.genericArgumentVarargs().getChildCount() === 0) { this.sb.push(capitalize(ctx.getChild(0).getText())); diff --git a/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts b/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts index 070a88fceb6..17a3b5ad724 100644 --- a/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts +++ b/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts @@ -58,7 +58,14 @@ export default class GremlinLang { let result = p.operator + '('; if (Array.isArray(p.value)) { - result += '[' + p.value.map(v => this._argAsString(v)).join(',') + ']'; + // If all elements are traversals, serialize as comma-separated args (no brackets) + // This matches the server grammar: within(trav1, trav2) via genericArgumentVarargs + const allTraversals = p.value.length > 0 && p.value.every((v: any) => v != null && typeof v.getGremlinLang === 'function'); + if (allTraversals) { + result += p.value.map((v: any) => this._argAsString(v)).join(','); + } else { + result += '[' + p.value.map((v: any) => this._argAsString(v)).join(',') + ']'; + } } else { result += this._argAsString(p.value); if (p.other !== undefined && p.other !== null) { @@ -99,7 +106,7 @@ export default class GremlinLang { if (arg === -Infinity) return '-Infinity'; if (!Number.isInteger(arg)) return String(arg) + 'D'; if (arg >= INT32_MIN && arg <= INT32_MAX) return String(arg); - // Outside safe integer range, values have lost precision and may exceed Java Long — emit as Double. + // Outside safe integer range, values have lost precision and may exceed Java Long - emit as Double. if (arg > Number.MAX_SAFE_INTEGER || arg < -Number.MAX_SAFE_INTEGER) return String(arg) + 'D'; return String(arg) + 'L'; } diff --git a/gremlin-js/gremlin-javascript/lib/process/traversal.ts b/gremlin-js/gremlin-javascript/lib/process/traversal.ts index f4f6db0bcda..a8f3abfc193 100644 --- a/gremlin-js/gremlin-javascript/lib/process/traversal.ts +++ b/gremlin-js/gremlin-javascript/lib/process/traversal.ts @@ -370,6 +370,9 @@ export class P { if (args.length === 1 && Array.isArray(args[0])) { return new P('within', args[0], null); } + if (args.length === 1 && args[0] != null && typeof args[0].getGremlinLang === 'function') { + return new P('within', args[0], null); + } return new P('within', args, null); } @@ -377,6 +380,9 @@ export class P { if (args.length === 1 && Array.isArray(args[0])) { return new P('without', args[0], null); } + if (args.length === 1 && args[0] != null && typeof args[0].getGremlinLang === 'function') { + return new P('without', args[0], null); + } return new P('without', args, null); } diff --git a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js index d4e6e97e758..bd0aa8a83a5 100644 --- a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js +++ b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js @@ -485,6 +485,37 @@ const gremlins = { g_V_hasXlabel_personX: [function({g}) { return g.V().has(T.label, "person") }], g_V_hasXlabel_eqXpersonXX: [function({g}) { return g.V().has(T.label, P.eq("person")) }], g_V_hasXname_nullX: [function({g}) { return g.V().has("name", null) }], + g_V_hasXname_constantXmarkoXX: [function({g}) { return g.V().has("name", __.constant("marko")) }], + g_V_hasXname_VXvid1X_outXknowsX_valuesXnameXX: [function({g, vid1}) { return g.V().has("name", __.V(vid1).out("knows").values("name").order()) }], + g_V_hasXname_valuesXnonexistentXX: [function({g}) { return g.V().has("name", __.values("nonexistent")) }], + g_V_hasXname_notXidentityXX: [function({g}) { return g.V().has("name", __.not(__.identity())) }], + g_V_hasXage_gtXconstantX29XXX: [function({g}) { return g.V().has("age", P.gt(__.constant(29))) }], + g_V_hasXage_lteXconstantX27XXX: [function({g}) { return g.V().has("age", P.lte(__.constant(27))) }], + g_V_hasXage_neqXconstantX32XXX: [function({g}) { return g.V().has("age", P.neq(__.constant(32))) }], + g_V_hasXname_eqXconstantXmarkoXXX: [function({g}) { return g.V().has("name", P.eq(__.constant("marko"))) }], + g_V_hasXage_ltXconstantX29XXX: [function({g}) { return g.V().has("age", P.lt(__.constant(29))) }], + g_V_hasXage_gteXconstantX32XXX: [function({g}) { return g.V().has("age", P.gte(__.constant(32))) }], + g_V_hasXage_eqXvaluesXnonexistentXXX: [function({g}) { return g.V().has("age", P.eq(__.values("nonexistent"))) }], + g_V_hasXlabel_constantXpersonXX: [function({g}) { return g.V().has(T.label, __.constant("person")) }], + g_V_hasXperson_name_constantXmarkoXX_age: [function({g}) { return g.V().has("person", "name", __.constant("marko")).values("age") }], + g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_constantXpeterXX_foldXX: [function({g, vid1}) { return g.V().has("name", P.within(__.union(__.V(vid1).out("knows").values("name"), __.constant("peter")).fold())) }], + g_V_hasXname_withinXvaluesXnonexistentX_constantXmarkoXXX: [function({g}) { return g.V().has("name", P.within(__.values("nonexistent"), __.constant("marko"))) }], + g_V_hasXname_withinXvaluesXnonexistentX_valuesXnonexistent2XXX: [function({g}) { return g.V().has("name", P.within(__.values("nonexistent"), __.values("nonexistent2"))) }], + g_V_hasXname_withoutXconstantXmarkoX_constantXvadasX_constantXpeterXXX: [function({g}) { return g.V().has("name", P.without(__.constant("marko"), __.constant("vadas"), __.constant("peter"))) }], + g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_VXvid3X_outXcreatedX_valuesXnameXX_foldXX: [function({g, vid3, vid1}) { return g.V().has("name", P.within(__.union(__.V(vid1).out("knows").values("name"), __.V(vid3).out("created").values("name")).fold())) }], + g_V_hasLabelXsoftwareX_hasXname_withoutXunionXVXvid1X_outXcreatedX_valuesXnameX_VXvid4X_outXcreatedX_valuesXnameXX_foldXX: [function({g, vid4, vid1}) { return g.V().hasLabel("software").has("name", P.without(__.union(__.V(vid1).out("created").values("name"), __.V(vid4).out("created").values("name")).fold())) }], + g_V_hasLabelXpersonX_valuesXageX_isXwithinXunionXVXvid1X_valuesXageX_V_hasXname_lopX_inXcreatedX_valuesXageXX_foldXX: [function({g, vid1}) { return g.V().hasLabel("person").values("age").is(P.within(__.union(__.V(vid1).values("age"), __.V().has("name", "lop").in_("created").values("age")).fold())) }], + g_VXvid1X_outEXknowsX_filterXinV_hasXname_withinXunionXV_hasXname_lopX_inXcreatedX_valuesXnameX_V_hasXname_rippleX_inXcreatedX_valuesXnameXX_foldXXXX: [function({g, vid1}) { return g.V(vid1).outE("knows").filter(__.inV().has("name", P.within(__.union(__.V().has("name", "lop").in_("created").values("name"), __.V().has("name", "ripple").in_("created").values("name")).fold()))) }], + g_V_hasLabelXconstantXpersonXX: [function({g}) { return g.V().hasLabel(__.constant("person")) }], + g_V_hasIdXeqXVXvid1X_idXX: [function({g, vid1}) { return g.V().hasId(P.eq(__.V(vid1).id())) }], + g_V_hasIdXVXvid1X_idXX: [function({g, vid1}) { return g.V().hasId(__.V(vid1).id()) }], + g_V_propertiesXageX_hasKeyXconstantXageXX: [function({g}) { return g.V().properties("age").hasKey(__.constant("age")) }], + g_V_propertiesXageX_hasKeyXeqXconstantXageXXX: [function({g}) { return g.V().properties("age").hasKey(P.eq(__.constant("age"))) }], + g_V_propertiesXageX_hasValueXconstantX29XX: [function({g}) { return g.V().properties("age").hasValue(__.constant(29)) }], + g_V_propertiesXageX_hasValueXeqXconstantX29XXX: [function({g}) { return g.V().properties("age").hasValue(P.eq(__.constant(29))) }], + g_VXvid1X_asXaX_V_hasXage_gtXselectXaX_valuesXageXXX_valuesXnameX: [function({g, vid1}) { return g.V(vid1).as("a").V().has("age", P.gt(__.select("a").values("age"))).values("name") }], + g_withSackX29X_V_hasXage_gtXsackXX_valuesXnameX: [function({g}) { return g.withSack(29).V().has("age", P.gt(__.sack())).values("name") }], + g_V_hasXname_markoX_outEXknowsX_hasXweight_gteXconstantX05XXX: [function({g}) { return g.V().has("name", "marko").outE("knows").has("weight", P.gte(__.constant(0.5))) }], g_V_hasIdXemptyX_count: [function({g, xx1}) { return g.V().hasId(xx1).count() }], g_V_hasIdXwithinXemptyXX_count: [function({g}) { return g.V().hasId(P.within([])).count() }], g_V_hasIdXwithoutXemptyXX_count: [function({g}) { return g.V().hasId(P.without([])).count() }], @@ -544,6 +575,28 @@ const gremlins = { g_V_valuesXageX_isXgte_29vaarX_isXlt_34varX: [function({g, xx1, xx2}) { return g.V().values("age").is(P.gte(xx1)).is(P.lt(xx2)) }], g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(1)).values("name") }], g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(P.gte(2))).values("name") }], + g_V_valuesXageX_isXconstantX29XX: [function({g}) { return g.V().values("age").is(__.constant(29)) }], + g_V_valuesXnameX_isXconstantXmarkoXX: [function({g}) { return g.V().values("name").is(__.constant("marko")) }], + g_V_valuesXageX_isXgtXconstantX29XXX: [function({g}) { return g.V().values("age").is(P.gt(__.constant(29))) }], + g_V_valuesXageX_isXltXconstantX32XXX: [function({g}) { return g.V().values("age").is(P.lt(__.constant(32))) }], + g_V_valuesXageX_isXneqXconstantX35XXX: [function({g}) { return g.V().values("age").is(P.neq(__.constant(35))) }], + g_V_valuesXageX_isXwithinXVXvid1X_outXknowsX_valuesXageXXX: [function({g, vid1}) { return g.V().values("age").is(P.within(__.V(vid1).out("knows").values("age").fold())) }], + g_V_valuesXageX_isXconstantX99999XX: [function({g}) { return g.V().values("age").is(__.constant(99999)) }], + g_V_hasLabelXpersonX_valuesXageX_chooseXgtXconstantX29XX_olderX: [function({g}) { return g.V().hasLabel("person").values("age").choose(__.is(P.gt(__.constant(29))), __.constant("older than marko"), __.constant("not older")) }], + g_V_hasLabelXpersonX_valuesXageX_chooseXgteXmeanAgeX_aboveX: [function({g}) { return g.V().hasLabel("person").values("age").choose(__.is(P.gte(__.V().hasLabel("person").values("age").mean())), __.constant("above average"), __.constant("below average")) }], + g_VXvid1X_outXknowsX_valuesXageX_fold_allXgteXconstantX27XXX: [function({g, vid1}) { return g.V(vid1).out("knows").values("age").fold().all(P.gte(__.constant(27))) }], + g_VXvid1X_outXknowsX_valuesXageX_fold_allXgtXconstantX27XXX: [function({g, vid1}) { return g.V(vid1).out("knows").values("age").fold().all(P.gt(__.constant(27))) }], + g_VXvid1X_outXknowsX_valuesXageX_fold_anyXeqXconstantX32XXX: [function({g, vid1}) { return g.V(vid1).out("knows").values("age").fold().any(P.eq(__.constant(32))) }], + g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX35XXX: [function({g, vid1}) { return g.V(vid1).out("knows").values("age").fold().none(P.eq(__.constant(35))) }], + g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX32XXX: [function({g, vid1}) { return g.V(vid1).out("knows").values("age").fold().none(P.eq(__.constant(32))) }], + g_injectXnullX_isXeqXV9999_valuesXnameXXX: [function({g}) { return g.inject(null).is(P.eq(__.V(9999).values("name"))) }], + g_injectXmarkoX_isXV9999_valuesXnameXX: [function({g}) { return g.inject("marko").is(__.V(9999).values("name")) }], + g_injectXmarkoX_chooseXeqXV9999_valuesXnameXX_matched_unmatchedX: [function({g}) { return g.inject("marko").choose(__.is(P.eq(__.V(9999).values("name"))), __.constant("matched"), __.constant("unmatched")) }], + g_injectXlistX_noneXeqXV9999_valuesXnameXXX: [function({g}) { return g.inject(["marko", "josh"]).none(P.eq(__.V(9999).values("name"))) }], + g_V_hasXname_eqXV9999_valuesXnameXXX: [function({g}) { return g.V().has("name", P.eq(__.V(9999).values("name"))) }], + g_V_valuesXageX_isXwithoutXconstantX29X_constantX32XXX: [function({g}) { return g.V().values("age").is(P.without(__.constant(29), __.constant(32))) }], + g_VXvid1X_asXaX_V_valuesXageX_isXgtXselectXaX_valuesXageXXX: [function({g, vid1}) { return g.V(vid1).as("a").V().values("age").is(P.gt(__.select("a").values("age"))) }], + g_withSackX30X_V_valuesXageX_isXgtXsackXX: [function({g}) { return g.withSack(30).V().values("age").is(P.gt(__.sack())) }], g_V_valuesXageX_noneXgtX32XX: [function({g}) { return g.V().values("age").none(P.gt(32)) }], g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX: [function({g}) { return g.V().values("age").where(__.is(P.gt(33))).fold().none(P.lte(33)) }], g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX: [function({g}) { return g.V().values("age").order().by(Order.desc).fold().none(P.lt(10)) }], @@ -716,6 +769,16 @@ 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_whereXgtXconstantX29XXX: [function({g}) { return g.V().values("age").where(P.gt(__.constant(29))) }], + g_V_valuesXageX_whereXltXconstantX32XXX: [function({g}) { return g.V().values("age").where(P.lt(__.constant(32))) }], + g_V_valuesXageX_whereXeqXconstantX29XXX: [function({g}) { return g.V().values("age").where(P.eq(__.constant(29))) }], + g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX: [function({g, vid1}) { return g.V().values("age").where(P.within(__.V(vid1).out("knows").values("age").fold())) }], + g_V_valuesXnameX_whereXneqXconstantXmarkoXXX: [function({g}) { return g.V().values("name").where(P.neq(__.constant("marko"))) }], + g_V_valuesXageX_whereXeqXconstantX99999XXX: [function({g}) { return g.V().values("age").where(P.eq(__.constant(99999))) }], + g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX: [function({g, vid1}) { return g.V().where(P.gt(__.V(vid1).values("age"))).by("age").values("name") }], + g_VX1X_asXaX_V_valuesXageX_whereXgteXconstantX0XX_andXneqXaXXX_byX_byXageX: [function({g, vid1}) { return g.V(vid1).as("a").V().hasLabel("person").values("age").where(P.gte(__.constant(0)).and(P.neq("a"))).by().by("age") }], + g_VX1X_asXaX_V_valuesXageX_whereXneqXaX_andXgtXVXvid1X_valuesXageXXXX_byX_byXageX: [function({g, vid1}) { return g.V(vid1).as("a").V().hasLabel("person").values("age").where(P.neq("a").and(P.gt(__.V(vid1).values("age")))).by().by("age") }], + g_VX1X_asXaX_V_valuesXageX_whereXeqXVXvid1X_valuesXageXX_orXeqXaXXX_byX_byXageX: [function({g, vid1}) { return g.V(vid1).as("a").V().hasLabel("person").values("age").where(P.eq(__.V(vid1).values("age")).or(P.eq("a"))).by().by("age") }], 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() }], @@ -837,6 +900,23 @@ const gremlins = { g_withoutStrategiesXSeedStrategyX_V: [function({g}) { return g.withoutStrategies(SeedStrategy).V() }], g_withStrategiesXStandardVerificationStrategyX_V: [function({g}) { return g.withStrategies(new StandardVerificationStrategy()).V() }], g_withoutStrategiesXStandardVerificationStrategyX_V: [function({g}) { return g.withoutStrategies(StandardVerificationStrategy).V() }], + g_V_hasXname_addVXxX_valuesXnameXX_rejected: [function({g}) { return g.V().has("name", __.addV("x").values("name")) }], + g_V_hasXname_V_drop_constantXxXX_rejected: [function({g}) { return g.V().has("name", __.V().drop().constant("x")) }], + g_V_hasXname_V_mapXaddVXxXX_valuesXnameXX_rejected: [function({g}) { return g.V().has("name", __.V().map(__.addV("x")).values("name")) }], + g_V_hasXname_eqXaddVXxX_valuesXnameXXX_rejected: [function({g}) { return g.V().has("name", P.eq(__.addV("x").values("name"))) }], + g_V_hasXname_withinXaddVXxX_valuesXnameXXX_rejected: [function({g}) { return g.V().has("name", P.within(__.addV("x").values("name"))) }], + g_V_hasXage_gtXaddVXxX_valuesXageXXX_rejected: [function({g}) { return g.V().has("age", P.gt(__.addV("x").values("age"))) }], + g_V_valuesXageX_isXaddVXxX_valuesXageXX_rejected: [function({g}) { return g.V().values("age").is(__.addV("x").values("age")) }], + g_V_valuesXageX_isXgtXaddVXxX_valuesXageXXX_rejected: [function({g}) { return g.V().values("age").is(P.gt(__.addV("x").values("age"))) }], + g_V_VXaddVXxX_idX_rejected: [function({g}) { return g.V().V(__.addV("x").id()) }], + g_V_EXaddVXxX_idX_rejected: [function({g}) { return g.V().E(__.addV("x").id()) }], + g_VXaddVXxX_idX_rejected: [function({g}) { return g.V(__.addV("x").id()) }], + g_EXaddVXxX_idX_rejected: [function({g}) { return g.E(__.addV("x").id()) }], + g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected: [function({g}) { return g.V().property(__.V().map(__.drop()).project("x").by("name")) }], + g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected: [function({g}) { return g.V().property(__.addV("temp").project("k").by("name")) }], + g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification: [function({g, vid1}) { return g.V().has("name", __.V(vid1).values("name")) }], + g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification: [function({g, vid1}) { return g.V().has("age", P.gt(__.V(vid1).values("age"))) }], + g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification: [function({g, vid1}) { return g.V(vid1).V(__.out("knows").id()).values("name") }], g_withStrategiesXSubgraphStrategyXsubgraphAXX_V: [function({g}) { return g.withStrategies(new SubgraphStrategy({vertices: __.has("name", P.within("josh", "lop", "ripple"))})).V() }], g_withStrategiesXSubgraphStrategyXsubgraphAXX_E: [function({g}) { return g.withStrategies(new SubgraphStrategy({vertices: __.has("name", P.within("josh", "lop", "ripple"))})).E() }], g_withStrategiesXSubgraphStrategyXsubgraphAXX_VX4X_outE: [function({g, vid4}) { return g.withStrategies(new SubgraphStrategy({vertices: __.has("name", P.within("josh", "lop", "ripple"))})).V(vid4).outE() }], @@ -1190,6 +1270,10 @@ const gremlins = { g_VX1X_outEXknowsX_bothV: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV() }], g_VX1X_outEXknowsX_bothV_name: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV().values("name") }], g_V_toEXout_knowsvarX_valuesXweightX: [function({g, xx1}) { return g.V().toE(Direction.OUT, xx1).values("weight") }], + g_VXvid1X_EXoutE_idX: [function({g, vid1}) { return g.V(vid1).E(__.outE().id()) }], + g_VXvid1X_outEXknowsX_hasXinV_name_vadasX_id_EXidentityX: [function({g, vid1}) { return g.V(vid1).outE("knows").filter(__.inV().has("name", "vadas")).id().E(__.identity()) }], + g_injectX9999X_EXidentityX: [function({g}) { return g.inject(9999).E(__.identity()) }], + g_EXVXvid1X_outE_idX: [function({g, vid1}) { return g.E(__.V(vid1).outE().id()) }], g_VX1X_properties_element: [function({g, vid2}) { return g.V(vid2).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() }], @@ -1854,6 +1938,12 @@ const gremlins = { g_V_outXknowsX_V_name: [function({g}) { return g.V().out("knows").V().values("name") }], g_V_hasXname_GarciaX_inXsungByX_asXsongX_V_hasXname_Willie_DixonX_inXwrittenByX_whereXeqXsongXX_name: [function({g}) { return g.V().has("artist", "name", "Garcia").in_("sungBy").as("song").V().has("artist", "name", "Willie_Dixon").in_("writtenBy").where(P.eq("song")).values("name") }], g_V_hasLabelXpersonX_asXpX_VXsoftwareX_addInEXuses_pX: [function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", "peter").property("age", 35).as("peter").addE("knows").from_("marko").to("vadas").property("weight", 0.5).addE("knows").from_("marko").to("josh").property("weight", 1.0).addE("created").from_("marko").to("lop").property("weight", 0.4).addE("created").from_("josh").to("ripple").property("weight", 1.0).addE("created").from_("josh").to("lop").property("weight", 0.4).addE("created").from_("peter").to("lop").property("weight", 0.2) }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.V().hasLabel("person").as("p").V(xx1).addE("uses").from_("p") }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.E().hasLabel("uses") }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.V(vid1).outE("uses") }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.V(vid2).outE("uses") }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.V(vid3).inE("uses") }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.V(vid4).outE("uses") }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.V(vid5).inE("uses") }, function({g, xx1, vid1, vid2, vid3, vid4, vid5, vid6}) { return g.V(vid6).outE("uses") }], + g_VXvid1X_id_VXidentityX_name: [function({g, vid1}) { return g.V(vid1).id().V(__.identity()).values("name") }], + g_VXvid1_vid2X_id_VXidentityX_name: [function({g, vid2, vid1}) { return g.V(vid1, vid2).id().V(__.identity()).values("name") }], + g_VXvid1X_id_asXbookmarkX_V_hasXname_joshX_VXselectXbookmarkXX_name: [function({g, vid1}) { return g.V(vid1).id().as("bookmark").V().has("name", "josh").V(__.select("bookmark")).values("name") }], + g_VXvid1X_VXoutXknowsX_idX_name: [function({g, vid1}) { return g.V(vid1).V(__.out("knows").id()).values("name") }], + g_injectX9999X_VXidentityX: [function({g}) { return g.inject(9999).V(__.identity()) }], + g_VXVXvid1X_idX_name: [function({g, vid1}) { return g.V(__.V(vid1).id()).values("name") }], InjectXnullX_eqXnullX: [function({g}) { return g.inject(null).is(P.eq(null)) }], InjectXnullX_neqXnullX: [function({g}) { return g.inject(null).is(P.neq(null)) }], InjectXnullX_ltXnullX: [function({g}) { return g.inject(null).is(P.lt(null)) }], @@ -2126,6 +2216,16 @@ const gremlins = { g_injectX1_3_100_300X_list: [function({g}) { return g.inject([1, 3, 100, 300]) }], g_injectX1_3_100_300X_set: [function({g}) { return g.inject(new Set([1, 3, 100, 300])) }], g_injectX1_1X_set: [function({g}) { return g.inject(new Set([1, 1])) }], + g_VXvid2X_propertyXalias_VXvid1X_valuesXnameXX: [function({g, vid2, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27).addV("software").property("name", "lop").property("lang", "java").addV("person").property("name", "josh").property("age", 32).addV("person").property("name", "peter").property("age", 35).addV("software").property("name", "ripple").property("lang", "java") }, function({g, vid2, vid1}) { return g.V(vid2).property("alias", __.V(vid1).values("name")) }, function({g, vid2, vid1}) { return g.V().has("alias", "marko") }], + g_VXvid1X_propertyXcreatorCount_VXvid1X_inXcreatedX_countX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("person").property("name", "peter").property("age", 35).as("peter").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addE("knows").from_("marko").to(__.V().has("name", "vadas")).addE("knows").from_("marko").to("josh").addE("created").from_("marko").to("lop").addE("created").from_("josh").to("lop").addE("created").from_("josh").to("ripple").addE("created").from_("peter").to("lop") }, function({g, vid1}) { return g.V(vid1).property("creatorCount", __.V(vid1).in_("created").count()) }, function({g, vid1}) { return g.V().has("creatorCount", 3) }], + g_VXvid1X_propertyXknownCount_outXknowsX_countX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").addV("person").property("name", "josh").property("age", 32).as("josh").addV("person").property("name", "peter").property("age", 35).addV("software").property("name", "ripple").property("lang", "java").addE("knows").from_("marko").to("vadas").addE("knows").from_("marko").to("josh") }, function({g, vid1}) { return g.V(vid1).property("knownCount", __.out("knows").count()) }, function({g, vid1}) { return g.V().has("knownCount", 2) }], + g_VXvid1X_propertyXcreator_inXcreatedX_valuesXnameXX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("person").property("name", "peter").property("age", 35).as("peter").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addE("knows").from_("marko").to(__.V().has("name", "vadas")).addE("knows").from_("marko").to("josh").addE("created").from_("marko").to("lop").addE("created").from_("josh").to("lop").addE("created").from_("josh").to("ripple").addE("created").from_("peter").to("lop") }, function({g, vid1}) { return g.V(vid1).property("creator", __.in_("created").values("name")) }, function({g, vid1}) { return g.V().has("creator") }], + g_VXvid2X_propertyXVXvid1X_projectXfriendCount_softwareCreatedXX: [function({g, vid2, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("person").property("name", "peter").property("age", 35).as("peter").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addE("knows").from_("marko").to("vadas").addE("knows").from_("marko").to("josh").addE("created").from_("marko").to("lop").addE("created").from_("josh").to("lop").addE("created").from_("josh").to("ripple").addE("created").from_("peter").to("lop") }, function({g, vid2, vid1}) { return g.V(vid2).property(__.V(vid1).project("friendCount", "softwareCreated").by(__.out("knows").count()).by(__.out("created").values("name"))) }, function({g, vid2, vid1}) { return g.V().has("friendCount", 2) }, function({g, vid2, vid1}) { return g.V().has("softwareCreated", "lop") }], + g_VXvid2X_propertyXVXvid1X_projectXoriginalName_originalLabelX_byXnameX_byXlabelXX: [function({g, vid2, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).addV("person").property("name", "peter").property("age", 35).addV("software").property("name", "ripple").property("lang", "java") }, function({g, vid2, vid1}) { return g.V(vid2).property(__.V(vid1).project("originalName", "originalLabel").by(__.values("name")).by(__.label())) }, function({g, vid2, vid1}) { return g.V(vid2).has("originalName", "marko") }, function({g, vid2, vid1}) { return g.V(vid2).has("originalLabel", "person") }], + g_VXvid1X_propertyXlist_friends_outXknowsX_valuesXnameXX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").addV("person").property("name", "josh").property("age", 32).as("josh").addV("person").property("name", "peter").property("age", 35).addV("software").property("name", "ripple").property("lang", "java").addE("knows").from_("marko").to("vadas").addE("knows").from_("marko").to("josh") }, function({g, vid1}) { return g.V(vid1).property(Cardinality.list, "friends", __.out("knows").values("name")) }, function({g, vid1}) { return g.V(vid1).properties("friends") }], + g_VXvid1X_propertyXset_langs_outXcreatedX_valuesXlangXX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27).addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("person").property("name", "peter").property("age", 35).addV("software").property("name", "ripple").property("lang", "java").as("ripple").addE("created").from_("josh").to("lop").addE("created").from_("josh").to("ripple") }, function({g, vid1}) { return g.V(vid1).property(Cardinality.set, "langs", __.out("created").values("lang")) }, function({g, vid1}) { return g.V(vid1).properties("langs") }], + g_VXvid1X_propertyXsingle_friend_outXknowsX_valuesXnameXX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").addV("person").property("name", "josh").property("age", 32).as("josh").addV("person").property("name", "peter").property("age", 35).addV("software").property("name", "ripple").property("lang", "java").addE("knows").from_("marko").to("vadas").addE("knows").from_("marko").to("josh") }, function({g, vid1}) { return g.V(vid1).property(Cardinality.single, "friend", __.out("knows").values("name")) }], + g_VXvid1X_propertyXVXvid1X_groupX_byXidX_byXvaluesXnameXXX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g, vid1}) { return g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values("name"))) }], g_io_readXkryoX: [function({g}) { return g.io("data/tinkerpop-modern.kryo").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], g_io_read_withXreader_gryoX: [function({g}) { return g.io("data/tinkerpop-modern.kryo").with_(IO.reader, IO.gryo).read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], g_io_readXgraphsonX: [function({g}) { return g.io("data/tinkerpop-modern.json").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }], diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4 index 31205483b3b..881c4d3a1ce 100644 --- a/gremlin-language/src/main/antlr4/Gremlin.g4 +++ b/gremlin-language/src/main/antlr4/Gremlin.g4 @@ -124,10 +124,12 @@ traversalSourceSpawnMethod_addV traversalSourceSpawnMethod_E : K_E LPAREN genericArgumentVarargs RPAREN + | K_E LPAREN nestedTraversal RPAREN ; traversalSourceSpawnMethod_V : K_V LPAREN genericArgumentVarargs RPAREN + | K_V LPAREN nestedTraversal RPAREN ; traversalSourceSpawnMethod_inject @@ -319,10 +321,12 @@ traversalMethod traversalMethod_V : K_V LPAREN genericArgumentVarargs RPAREN + | K_V LPAREN nestedTraversal RPAREN ; traversalMethod_E : K_E LPAREN genericArgumentVarargs RPAREN + | K_E LPAREN nestedTraversal RPAREN ; traversalMethod_addE @@ -553,10 +557,13 @@ traversalMethod_has : K_HAS LPAREN stringNullableLiteral RPAREN #traversalMethod_has_String | K_HAS LPAREN stringNullableLiteral COMMA genericArgument RPAREN #traversalMethod_has_String_Object | K_HAS LPAREN stringNullableLiteral COMMA traversalPredicate RPAREN #traversalMethod_has_String_P + | K_HAS LPAREN stringNullableLiteral COMMA nestedTraversal RPAREN #traversalMethod_has_String_Traversal | K_HAS LPAREN stringNullableArgument COMMA stringNullableLiteral COMMA genericArgument RPAREN #traversalMethod_has_String_String_Object | K_HAS LPAREN stringNullableArgument COMMA stringNullableLiteral COMMA traversalPredicate RPAREN #traversalMethod_has_String_String_P + | K_HAS LPAREN stringNullableArgument COMMA stringNullableLiteral COMMA nestedTraversal RPAREN #traversalMethod_has_String_String_Traversal | K_HAS LPAREN traversalT COMMA genericArgument RPAREN #traversalMethod_has_T_Object | K_HAS LPAREN traversalT COMMA traversalPredicate RPAREN #traversalMethod_has_T_P + | K_HAS LPAREN traversalT COMMA nestedTraversal RPAREN #traversalMethod_has_T_Traversal ; traversalMethod_hasId @@ -567,11 +574,13 @@ traversalMethod_hasId traversalMethod_hasKey : K_HASKEY LPAREN traversalPredicate RPAREN #traversalMethod_hasKey_P | K_HASKEY LPAREN stringNullableLiteral (COMMA stringNullableLiteralVarargs)? RPAREN #traversalMethod_hasKey_String_String + | K_HASKEY LPAREN nestedTraversal RPAREN #traversalMethod_hasKey_Traversal ; traversalMethod_hasLabel : K_HASLABEL LPAREN traversalPredicate RPAREN #traversalMethod_hasLabel_P | K_HASLABEL LPAREN stringNullableArgument (COMMA stringNullableArgumentVarargs)? RPAREN #traversalMethod_hasLabel_String_String + | K_HASLABEL LPAREN nestedTraversal RPAREN #traversalMethod_hasLabel_Traversal ; traversalMethod_hasNot @@ -581,6 +590,7 @@ traversalMethod_hasNot traversalMethod_hasValue : K_HASVALUE LPAREN genericArgument (COMMA genericArgumentVarargs)? RPAREN #traversalMethod_hasValue_Object_Object | K_HASVALUE LPAREN traversalPredicate RPAREN #traversalMethod_hasValue_P + | K_HASVALUE LPAREN nestedTraversal RPAREN #traversalMethod_hasValue_Traversal ; traversalMethod_id @@ -775,9 +785,12 @@ traversalMethod_properties traversalMethod_property : K_PROPERTY LPAREN traversalCardinality COMMA genericLiteral COMMA genericArgument (COMMA genericArgumentVarargs)? RPAREN #traversalMethod_property_Cardinality_Object_Object_Object + | K_PROPERTY LPAREN traversalCardinality COMMA genericLiteral COMMA nestedTraversal RPAREN #traversalMethod_property_Cardinality_Object_Traversal | K_PROPERTY LPAREN traversalCardinality COMMA genericMapNullableArgument RPAREN # traversalMethod_property_Cardinality_Object | K_PROPERTY LPAREN genericLiteral COMMA genericArgument (COMMA genericArgumentVarargs)? RPAREN #traversalMethod_property_Object_Object_Object + | K_PROPERTY LPAREN genericLiteral COMMA nestedTraversal RPAREN #traversalMethod_property_Object_Traversal | K_PROPERTY LPAREN genericMapNullableArgument RPAREN # traversalMethod_property_Object + | K_PROPERTY LPAREN nestedTraversal RPAREN #traversalMethod_property_Traversal ; traversalMethod_propertyMap @@ -1195,10 +1208,12 @@ traversalBiFunction traversalPredicate_eq : (K_P DOT K_EQ | K_EQ) LPAREN genericArgument RPAREN + | (K_P DOT K_EQ | K_EQ) LPAREN nestedTraversal RPAREN ; traversalPredicate_neq : (K_P DOT K_NEQ | K_NEQ) LPAREN genericArgument RPAREN + | (K_P DOT K_NEQ | K_NEQ) LPAREN nestedTraversal RPAREN ; traversalPredicate_typeOf @@ -1208,40 +1223,49 @@ traversalPredicate_typeOf traversalPredicate_lt : (K_P DOT K_LT | K_LT) LPAREN genericArgument RPAREN + | (K_P DOT K_LT | K_LT) LPAREN nestedTraversal RPAREN ; traversalPredicate_lte : (K_P DOT K_LTE | K_LTE) LPAREN genericArgument RPAREN + | (K_P DOT K_LTE | K_LTE) LPAREN nestedTraversal RPAREN ; traversalPredicate_gt : (K_P DOT K_GT | K_GT) LPAREN genericArgument RPAREN + | (K_P DOT K_GT | K_GT) LPAREN nestedTraversal RPAREN ; traversalPredicate_gte : (K_P DOT K_GTE | K_GTE) LPAREN genericArgument RPAREN + | (K_P DOT K_GTE | K_GTE) LPAREN nestedTraversal RPAREN ; traversalPredicate_inside : (K_P DOT K_INSIDE | K_INSIDE) LPAREN genericArgument COMMA genericArgument RPAREN + | (K_P DOT K_INSIDE | K_INSIDE) LPAREN nestedTraversal COMMA nestedTraversal RPAREN ; traversalPredicate_outside : (K_P DOT K_OUTSIDE | K_OUTSIDE) LPAREN genericArgument COMMA genericArgument RPAREN + | (K_P DOT K_OUTSIDE | K_OUTSIDE) LPAREN nestedTraversal COMMA nestedTraversal RPAREN ; traversalPredicate_between : (K_P DOT K_BETWEEN | K_BETWEEN) LPAREN genericArgument COMMA genericArgument RPAREN + | (K_P DOT K_BETWEEN | K_BETWEEN) LPAREN nestedTraversal COMMA nestedTraversal RPAREN ; traversalPredicate_within : (K_P DOT K_WITHIN | K_WITHIN) LPAREN RPAREN | (K_P DOT K_WITHIN | K_WITHIN) LPAREN genericArgumentVarargs RPAREN + | (K_P DOT K_WITHIN | K_WITHIN) LPAREN nestedTraversal RPAREN ; traversalPredicate_without : (K_P DOT K_WITHOUT | K_WITHOUT) LPAREN RPAREN | (K_P DOT K_WITHOUT | K_WITHOUT) LPAREN genericArgumentVarargs RPAREN + | (K_P DOT K_WITHOUT | K_WITHOUT) LPAREN nestedTraversal RPAREN ; traversalPredicate_not @@ -1250,26 +1274,32 @@ traversalPredicate_not traversalPredicate_containing : (K_TEXTP DOT K_CONTAINING | K_CONTAINING) LPAREN stringArgument RPAREN + | (K_TEXTP DOT K_CONTAINING | K_CONTAINING) LPAREN nestedTraversal RPAREN ; traversalPredicate_notContaining : (K_TEXTP DOT K_NOTCONTAINING | K_NOTCONTAINING) LPAREN stringArgument RPAREN + | (K_TEXTP DOT K_NOTCONTAINING | K_NOTCONTAINING) LPAREN nestedTraversal RPAREN ; traversalPredicate_startingWith : (K_TEXTP DOT K_STARTINGWITH | K_STARTINGWITH) LPAREN stringArgument RPAREN + | (K_TEXTP DOT K_STARTINGWITH | K_STARTINGWITH) LPAREN nestedTraversal RPAREN ; traversalPredicate_notStartingWith : (K_TEXTP DOT K_NOTSTARTINGWITH | K_NOTSTARTINGWITH) LPAREN stringArgument RPAREN + | (K_TEXTP DOT K_NOTSTARTINGWITH | K_NOTSTARTINGWITH) LPAREN nestedTraversal RPAREN ; traversalPredicate_endingWith : (K_TEXTP DOT K_ENDINGWITH | K_ENDINGWITH) LPAREN stringArgument RPAREN + | (K_TEXTP DOT K_ENDINGWITH | K_ENDINGWITH) LPAREN nestedTraversal RPAREN ; traversalPredicate_notEndingWith : (K_TEXTP DOT K_NOTENDINGWITH | K_NOTENDINGWITH) LPAREN stringArgument RPAREN + | (K_TEXTP DOT K_NOTENDINGWITH | K_NOTENDINGWITH) LPAREN nestedTraversal RPAREN ; traversalPredicate_regex diff --git a/gremlin-python/src/main/python/gremlin_python/process/traversal.py b/gremlin-python/src/main/python/gremlin_python/process/traversal.py index cbc035ee2c8..a8d5465d397 100644 --- a/gremlin-python/src/main/python/gremlin_python/process/traversal.py +++ b/gremlin-python/src/main/python/gremlin_python/process/traversal.py @@ -359,6 +359,8 @@ def within(*args): return P("within", args[0]) elif len(args) == 1 and type(args[0]) == set: return P("within", list(args[0])) + elif len(args) == 1 and isinstance(args[0], Traversal): + return P("within", args[0]) else: return P("within", list(args)) @@ -368,6 +370,8 @@ def without(*args): return P("without", args[0]) elif len(args) == 1 and type(args[0]) == set: return P("without", list(args[0])) + elif len(args) == 1 and isinstance(args[0], Traversal): + return P("without", args[0]) else: return P("without", list(args)) @@ -990,13 +994,22 @@ def _process_p_value(self, p): c = 0 res = [str(p).split('(')[0] + '('] if isinstance(p.value, list): - res.append('[') - for v in p.value: - if c > 0: - res.append(',') - res.append(self._arg_as_string(v)) - c += 1 - res.append(']') + # If all elements are Traversals, serialize as comma-separated args (no brackets) + # This matches the server grammar: within(trav1, trav2) via genericArgumentVarargs + if len(p.value) > 0 and all(isinstance(v, Traversal) for v in p.value): + for v in p.value: + if c > 0: + res.append(',') + res.append(self._arg_as_string(v)) + c += 1 + else: + res.append('[') + for v in p.value: + if c > 0: + res.append(',') + res.append(self._arg_as_string(v)) + c += 1 + res.append(']') else: res.append(self._arg_as_string(p.value)) if p.other is not None: diff --git a/gremlin-python/src/main/python/tests/feature/gremlin.py b/gremlin-python/src/main/python/tests/feature/gremlin.py index e111d52b734..e35588e0bc9 100644 --- a/gremlin-python/src/main/python/tests/feature/gremlin.py +++ b/gremlin-python/src/main/python/tests/feature/gremlin.py @@ -459,6 +459,37 @@ 'g_V_hasXlabel_personX': [(lambda g:g.V().has(T.label, 'person'))], 'g_V_hasXlabel_eqXpersonXX': [(lambda g:g.V().has(T.label, P.eq('person')))], 'g_V_hasXname_nullX': [(lambda g:g.V().has('name', None))], + 'g_V_hasXname_constantXmarkoXX': [(lambda g:g.V().has('name', __.constant('marko')))], + 'g_V_hasXname_VXvid1X_outXknowsX_valuesXnameXX': [(lambda g, vid1=None:g.V().has('name', __.V(vid1).out('knows').values('name').order()))], + 'g_V_hasXname_valuesXnonexistentXX': [(lambda g:g.V().has('name', __.values('nonexistent')))], + 'g_V_hasXname_notXidentityXX': [(lambda g:g.V().has('name', __.not_(__.identity())))], + 'g_V_hasXage_gtXconstantX29XXX': [(lambda g:g.V().has('age', P.gt(__.constant(29))))], + 'g_V_hasXage_lteXconstantX27XXX': [(lambda g:g.V().has('age', P.lte(__.constant(27))))], + 'g_V_hasXage_neqXconstantX32XXX': [(lambda g:g.V().has('age', P.neq(__.constant(32))))], + 'g_V_hasXname_eqXconstantXmarkoXXX': [(lambda g:g.V().has('name', P.eq(__.constant('marko'))))], + 'g_V_hasXage_ltXconstantX29XXX': [(lambda g:g.V().has('age', P.lt(__.constant(29))))], + 'g_V_hasXage_gteXconstantX32XXX': [(lambda g:g.V().has('age', P.gte(__.constant(32))))], + 'g_V_hasXage_eqXvaluesXnonexistentXXX': [(lambda g:g.V().has('age', P.eq(__.values('nonexistent'))))], + 'g_V_hasXlabel_constantXpersonXX': [(lambda g:g.V().has(T.label, __.constant('person')))], + 'g_V_hasXperson_name_constantXmarkoXX_age': [(lambda g:g.V().has('person', 'name', __.constant('marko')).values('age'))], + 'g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_constantXpeterXX_foldXX': [(lambda g, vid1=None:g.V().has('name', P.within(__.union(__.V(vid1).out('knows').values('name'), __.constant('peter')).fold())))], + 'g_V_hasXname_withinXvaluesXnonexistentX_constantXmarkoXXX': [(lambda g:g.V().has('name', P.within(__.values('nonexistent'), __.constant('marko'))))], + 'g_V_hasXname_withinXvaluesXnonexistentX_valuesXnonexistent2XXX': [(lambda g:g.V().has('name', P.within(__.values('nonexistent'), __.values('nonexistent2'))))], + 'g_V_hasXname_withoutXconstantXmarkoX_constantXvadasX_constantXpeterXXX': [(lambda g:g.V().has('name', P.without(__.constant('marko'), __.constant('vadas'), __.constant('peter'))))], + 'g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_VXvid3X_outXcreatedX_valuesXnameXX_foldXX': [(lambda g, vid3=None,vid1=None:g.V().has('name', P.within(__.union(__.V(vid1).out('knows').values('name'), __.V(vid3).out('created').values('name')).fold())))], + 'g_V_hasLabelXsoftwareX_hasXname_withoutXunionXVXvid1X_outXcreatedX_valuesXnameX_VXvid4X_outXcreatedX_valuesXnameXX_foldXX': [(lambda g, vid4=None,vid1=None:g.V().has_label('software').has('name', P.without(__.union(__.V(vid1).out('created').values('name'), __.V(vid4).out('created').values('name')).fold())))], + 'g_V_hasLabelXpersonX_valuesXageX_isXwithinXunionXVXvid1X_valuesXageX_V_hasXname_lopX_inXcreatedX_valuesXageXX_foldXX': [(lambda g, vid1=None:g.V().has_label('person').values('age').is_(P.within(__.union(__.V(vid1).values('age'), __.V().has('name', 'lop').in_('created').values('age')).fold())))], + 'g_VXvid1X_outEXknowsX_filterXinV_hasXname_withinXunionXV_hasXname_lopX_inXcreatedX_valuesXnameX_V_hasXname_rippleX_inXcreatedX_valuesXnameXX_foldXXXX': [(lambda g, vid1=None:g.V(vid1).out_e('knows').filter_(__.in_v().has('name', P.within(__.union(__.V().has('name', 'lop').in_('created').values('name'), __.V().has('name', 'ripple').in_('created').values('name')).fold()))))], + 'g_V_hasLabelXconstantXpersonXX': [(lambda g:g.V().has_label(__.constant('person')))], + 'g_V_hasIdXeqXVXvid1X_idXX': [(lambda g, vid1=None:g.V().has_id(P.eq(__.V(vid1).id_())))], + 'g_V_hasIdXVXvid1X_idXX': [(lambda g, vid1=None:g.V().has_id(__.V(vid1).id_()))], + 'g_V_propertiesXageX_hasKeyXconstantXageXX': [(lambda g:g.V().properties('age').has_key(__.constant('age')))], + 'g_V_propertiesXageX_hasKeyXeqXconstantXageXXX': [(lambda g:g.V().properties('age').has_key(P.eq(__.constant('age'))))], + 'g_V_propertiesXageX_hasValueXconstantX29XX': [(lambda g:g.V().properties('age').has_value(__.constant(29)))], + 'g_V_propertiesXageX_hasValueXeqXconstantX29XXX': [(lambda g:g.V().properties('age').has_value(P.eq(__.constant(29))))], + 'g_VXvid1X_asXaX_V_hasXage_gtXselectXaX_valuesXageXXX_valuesXnameX': [(lambda g, vid1=None:g.V(vid1).as_('a').V().has('age', P.gt(__.select('a').values('age'))).values('name'))], + 'g_withSackX29X_V_hasXage_gtXsackXX_valuesXnameX': [(lambda g:g.with_sack(29).V().has('age', P.gt(__.sack())).values('name'))], + 'g_V_hasXname_markoX_outEXknowsX_hasXweight_gteXconstantX05XXX': [(lambda g:g.V().has('name', 'marko').out_e('knows').has('weight', P.gte(__.constant(0.5))))], 'g_V_hasIdXemptyX_count': [(lambda g, xx1=None:g.V().has_id(xx1).count())], 'g_V_hasIdXwithinXemptyXX_count': [(lambda g:g.V().has_id(P.within([])).count())], 'g_V_hasIdXwithoutXemptyXX_count': [(lambda g:g.V().has_id(P.without([])).count())], @@ -518,6 +549,28 @@ 'g_V_valuesXageX_isXgte_29vaarX_isXlt_34varX': [(lambda g, xx1=None,xx2=None:g.V().values('age').is_(P.gte(xx1)).is_(P.lt(xx2)))], 'g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(1)).values('name'))], 'g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(P.gte(2))).values('name'))], + 'g_V_valuesXageX_isXconstantX29XX': [(lambda g:g.V().values('age').is_(__.constant(29)))], + 'g_V_valuesXnameX_isXconstantXmarkoXX': [(lambda g:g.V().values('name').is_(__.constant('marko')))], + 'g_V_valuesXageX_isXgtXconstantX29XXX': [(lambda g:g.V().values('age').is_(P.gt(__.constant(29))))], + 'g_V_valuesXageX_isXltXconstantX32XXX': [(lambda g:g.V().values('age').is_(P.lt(__.constant(32))))], + 'g_V_valuesXageX_isXneqXconstantX35XXX': [(lambda g:g.V().values('age').is_(P.neq(__.constant(35))))], + 'g_V_valuesXageX_isXwithinXVXvid1X_outXknowsX_valuesXageXXX': [(lambda g, vid1=None:g.V().values('age').is_(P.within(__.V(vid1).out('knows').values('age').fold())))], + 'g_V_valuesXageX_isXconstantX99999XX': [(lambda g:g.V().values('age').is_(__.constant(99999)))], + 'g_V_hasLabelXpersonX_valuesXageX_chooseXgtXconstantX29XX_olderX': [(lambda g:g.V().has_label('person').values('age').choose(__.is_(P.gt(__.constant(29))), __.constant('older than marko'), __.constant('not older')))], + 'g_V_hasLabelXpersonX_valuesXageX_chooseXgteXmeanAgeX_aboveX': [(lambda g:g.V().has_label('person').values('age').choose(__.is_(P.gte(__.V().has_label('person').values('age').mean())), __.constant('above average'), __.constant('below average')))], + 'g_VXvid1X_outXknowsX_valuesXageX_fold_allXgteXconstantX27XXX': [(lambda g, vid1=None:g.V(vid1).out('knows').values('age').fold().all_(P.gte(__.constant(27))))], + 'g_VXvid1X_outXknowsX_valuesXageX_fold_allXgtXconstantX27XXX': [(lambda g, vid1=None:g.V(vid1).out('knows').values('age').fold().all_(P.gt(__.constant(27))))], + 'g_VXvid1X_outXknowsX_valuesXageX_fold_anyXeqXconstantX32XXX': [(lambda g, vid1=None:g.V(vid1).out('knows').values('age').fold().any_(P.eq(__.constant(32))))], + 'g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX35XXX': [(lambda g, vid1=None:g.V(vid1).out('knows').values('age').fold().none(P.eq(__.constant(35))))], + 'g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX32XXX': [(lambda g, vid1=None:g.V(vid1).out('knows').values('age').fold().none(P.eq(__.constant(32))))], + 'g_injectXnullX_isXeqXV9999_valuesXnameXXX': [(lambda g:g.inject(None).is_(P.eq(__.V(9999).values('name'))))], + 'g_injectXmarkoX_isXV9999_valuesXnameXX': [(lambda g:g.inject('marko').is_(__.V(9999).values('name')))], + 'g_injectXmarkoX_chooseXeqXV9999_valuesXnameXX_matched_unmatchedX': [(lambda g:g.inject('marko').choose(__.is_(P.eq(__.V(9999).values('name'))), __.constant('matched'), __.constant('unmatched')))], + 'g_injectXlistX_noneXeqXV9999_valuesXnameXXX': [(lambda g:g.inject(['marko', 'josh']).none(P.eq(__.V(9999).values('name'))))], + 'g_V_hasXname_eqXV9999_valuesXnameXXX': [(lambda g:g.V().has('name', P.eq(__.V(9999).values('name'))))], + 'g_V_valuesXageX_isXwithoutXconstantX29X_constantX32XXX': [(lambda g:g.V().values('age').is_(P.without(__.constant(29), __.constant(32))))], + 'g_VXvid1X_asXaX_V_valuesXageX_isXgtXselectXaX_valuesXageXXX': [(lambda g, vid1=None:g.V(vid1).as_('a').V().values('age').is_(P.gt(__.select('a').values('age'))))], + 'g_withSackX30X_V_valuesXageX_isXgtXsackXX': [(lambda g:g.with_sack(30).V().values('age').is_(P.gt(__.sack())))], 'g_V_valuesXageX_noneXgtX32XX': [(lambda g:g.V().values('age').none(P.gt(32)))], 'g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX': [(lambda g:g.V().values('age').where(__.is_(P.gt(33))).fold().none(P.lte(33)))], 'g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX': [(lambda g:g.V().values('age').order().by(Order.desc).fold().none(P.lt(10)))], @@ -690,6 +743,16 @@ '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_whereXgtXconstantX29XXX': [(lambda g:g.V().values('age').where(P.gt(__.constant(29))))], + 'g_V_valuesXageX_whereXltXconstantX32XXX': [(lambda g:g.V().values('age').where(P.lt(__.constant(32))))], + 'g_V_valuesXageX_whereXeqXconstantX29XXX': [(lambda g:g.V().values('age').where(P.eq(__.constant(29))))], + 'g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX': [(lambda g, vid1=None:g.V().values('age').where(P.within(__.V(vid1).out('knows').values('age').fold())))], + 'g_V_valuesXnameX_whereXneqXconstantXmarkoXXX': [(lambda g:g.V().values('name').where(P.neq(__.constant('marko'))))], + 'g_V_valuesXageX_whereXeqXconstantX99999XXX': [(lambda g:g.V().values('age').where(P.eq(__.constant(99999))))], + 'g_V_whereXgtXVXvid1X_valuesXageXXX_byXageX_valuesXnameX': [(lambda g, vid1=None:g.V().where(P.gt(__.V(vid1).values('age'))).by('age').values('name'))], + 'g_VX1X_asXaX_V_valuesXageX_whereXgteXconstantX0XX_andXneqXaXXX_byX_byXageX': [(lambda g, vid1=None:g.V(vid1).as_('a').V().has_label('person').values('age').where(P.gte(__.constant(0)).and_(P.neq('a'))).by().by('age'))], + 'g_VX1X_asXaX_V_valuesXageX_whereXneqXaX_andXgtXVXvid1X_valuesXageXXXX_byX_byXageX': [(lambda g, vid1=None:g.V(vid1).as_('a').V().has_label('person').values('age').where(P.neq('a').and_(P.gt(__.V(vid1).values('age')))).by().by('age'))], + 'g_VX1X_asXaX_V_valuesXageX_whereXeqXVXvid1X_valuesXageXX_orXeqXaXXX_byX_byXageX': [(lambda g, vid1=None:g.V(vid1).as_('a').V().has_label('person').values('age').where(P.eq(__.V(vid1).values('age')).or_(P.eq('a'))).by().by('age'))], '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())], @@ -811,6 +874,23 @@ 'g_withoutStrategiesXSeedStrategyX_V': [(lambda g:g.without_strategies(SeedStrategy).V())], 'g_withStrategiesXStandardVerificationStrategyX_V': [(lambda g:g.with_strategies(StandardVerificationStrategy()).V())], 'g_withoutStrategiesXStandardVerificationStrategyX_V': [(lambda g:g.without_strategies(StandardVerificationStrategy).V())], + 'g_V_hasXname_addVXxX_valuesXnameXX_rejected': [(lambda g:g.V().has('name', __.add_v('x').values('name')))], + 'g_V_hasXname_V_drop_constantXxXX_rejected': [(lambda g:g.V().has('name', __.V().drop().constant('x')))], + 'g_V_hasXname_V_mapXaddVXxXX_valuesXnameXX_rejected': [(lambda g:g.V().has('name', __.V().map(__.add_v('x')).values('name')))], + 'g_V_hasXname_eqXaddVXxX_valuesXnameXXX_rejected': [(lambda g:g.V().has('name', P.eq(__.add_v('x').values('name'))))], + 'g_V_hasXname_withinXaddVXxX_valuesXnameXXX_rejected': [(lambda g:g.V().has('name', P.within(__.add_v('x').values('name'))))], + 'g_V_hasXage_gtXaddVXxX_valuesXageXXX_rejected': [(lambda g:g.V().has('age', P.gt(__.add_v('x').values('age'))))], + 'g_V_valuesXageX_isXaddVXxX_valuesXageXX_rejected': [(lambda g:g.V().values('age').is_(__.add_v('x').values('age')))], + 'g_V_valuesXageX_isXgtXaddVXxX_valuesXageXXX_rejected': [(lambda g:g.V().values('age').is_(P.gt(__.add_v('x').values('age'))))], + 'g_V_VXaddVXxX_idX_rejected': [(lambda g:g.V().V(__.add_v('x').id_()))], + 'g_V_EXaddVXxX_idX_rejected': [(lambda g:g.V().E(__.add_v('x').id_()))], + 'g_VXaddVXxX_idX_rejected': [(lambda g:g.V(__.add_v('x').id_()))], + 'g_EXaddVXxX_idX_rejected': [(lambda g:g.E(__.add_v('x').id_()))], + 'g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected': [(lambda g:g.V().property(__.V().map(__.drop()).project('x').by('name')))], + 'g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected': [(lambda g:g.V().property(__.add_v('temp').project('k').by('name')))], + 'g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification': [(lambda g, vid1=None:g.V().has('name', __.V(vid1).values('name')))], + 'g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification': [(lambda g, vid1=None:g.V().has('age', P.gt(__.V(vid1).values('age'))))], + 'g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification': [(lambda g, vid1=None:g.V(vid1).V(__.out('knows').id_()).values('name'))], 'g_withStrategiesXSubgraphStrategyXsubgraphAXX_V': [(lambda g:g.with_strategies(SubgraphStrategy(vertices=__.has('name', P.within('josh', 'lop', 'ripple')))).V())], 'g_withStrategiesXSubgraphStrategyXsubgraphAXX_E': [(lambda g:g.with_strategies(SubgraphStrategy(vertices=__.has('name', P.within('josh', 'lop', 'ripple')))).E())], 'g_withStrategiesXSubgraphStrategyXsubgraphAXX_VX4X_outE': [(lambda g, vid4=None:g.with_strategies(SubgraphStrategy(vertices=__.has('name', P.within('josh', 'lop', 'ripple')))).V(vid4).out_e())], @@ -1164,6 +1244,10 @@ 'g_VX1X_outEXknowsX_bothV': [(lambda g, vid1=None:g.V(vid1).out_e('knows').both_v())], 'g_VX1X_outEXknowsX_bothV_name': [(lambda g, vid1=None:g.V(vid1).out_e('knows').both_v().values('name'))], 'g_V_toEXout_knowsvarX_valuesXweightX': [(lambda g, xx1=None:g.V().to_e(Direction.OUT, xx1).values('weight'))], + 'g_VXvid1X_EXoutE_idX': [(lambda g, vid1=None:g.V(vid1).E(__.out_e().id_()))], + 'g_VXvid1X_outEXknowsX_hasXinV_name_vadasX_id_EXidentityX': [(lambda g, vid1=None:g.V(vid1).out_e('knows').filter_(__.in_v().has('name', 'vadas')).id_().E(__.identity()))], + 'g_injectX9999X_EXidentityX': [(lambda g:g.inject(9999).E(__.identity()))], + 'g_EXVXvid1X_outE_idX': [(lambda g, vid1=None:g.E(__.V(vid1).out_e().id_()))], 'g_VX1X_properties_element': [(lambda g, vid2=None:g.V(vid2).properties().element().limit(1))], 'g_V_properties_element': [(lambda g:g.V().properties().element())], 'g_V_propertiesXageX_element': [(lambda g:g.V().properties('age').element())], @@ -1828,6 +1912,12 @@ 'g_V_outXknowsX_V_name': [(lambda g:g.V().out('knows').V().values('name'))], 'g_V_hasXname_GarciaX_inXsungByX_asXsongX_V_hasXname_Willie_DixonX_inXwrittenByX_whereXeqXsongXX_name': [(lambda g:g.V().has('artist', 'name', 'Garcia').in_('sungBy').as_('song').V().has('artist', 'name', 'Willie_Dixon').in_('writtenBy').where(P.eq('song')).values('name'))], 'g_V_hasLabelXpersonX_asXpX_VXsoftwareX_addInEXuses_pX': [(lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').property('age', 35).as_('peter').add_e('knows').from_('marko').to('vadas').property('weight', 0.5).add_e('knows').from_('marko').to('josh').property('weight', 1.0).add_e('created').from_('marko').to('lop').property('weight', 0.4).add_e('created').from_('josh').to('ripple').property('weight', 1.0).add_e('created').from_('josh').to('lop').property('weight', 0.4).add_e('created').from_('peter').to('lop').property('weight', 0.2)), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.V().has_label('person').as_('p').V(xx1).add_e('uses').from_('p')), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.E().has_label('uses')), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.V(vid1).out_e('uses')), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.V(vid2).out_e('uses')), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.V(vid3).in_e('uses')), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.V(vid4).out_e('uses')), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.V(vid5).in_e('uses')), (lambda g, xx1=None,vid1=None,vid2=None,vid3=None,vid4=None,vid5=None,vid6=None:g.V(vid6).out_e('uses'))], + 'g_VXvid1X_id_VXidentityX_name': [(lambda g, vid1=None:g.V(vid1).id_().V(__.identity()).values('name'))], + 'g_VXvid1_vid2X_id_VXidentityX_name': [(lambda g, vid2=None,vid1=None:g.V(vid1, vid2).id_().V(__.identity()).values('name'))], + 'g_VXvid1X_id_asXbookmarkX_V_hasXname_joshX_VXselectXbookmarkXX_name': [(lambda g, vid1=None:g.V(vid1).id_().as_('bookmark').V().has('name', 'josh').V(__.select('bookmark')).values('name'))], + 'g_VXvid1X_VXoutXknowsX_idX_name': [(lambda g, vid1=None:g.V(vid1).V(__.out('knows').id_()).values('name'))], + 'g_injectX9999X_VXidentityX': [(lambda g:g.inject(9999).V(__.identity()))], + 'g_VXVXvid1X_idX_name': [(lambda g, vid1=None:g.V(__.V(vid1).id_()).values('name'))], 'InjectXnullX_eqXnullX': [(lambda g:g.inject(None).is_(P.eq(None)))], 'InjectXnullX_neqXnullX': [(lambda g:g.inject(None).is_(P.neq(None)))], 'InjectXnullX_ltXnullX': [(lambda g:g.inject(None).is_(P.lt(None)))], @@ -2100,6 +2190,16 @@ 'g_injectX1_3_100_300X_list': [(lambda g:g.inject([1, 3, 100, 300]))], 'g_injectX1_3_100_300X_set': [(lambda g:g.inject({1, 3, 100, 300}))], 'g_injectX1_1X_set': [(lambda g:g.inject({1, 1}))], + 'g_VXvid2X_propertyXalias_VXvid1X_valuesXnameXX': [(lambda g, vid2=None,vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java')), (lambda g, vid2=None,vid1=None:g.V(vid2).property('alias', __.V(vid1).values('name'))), (lambda g, vid2=None,vid1=None:g.V().has('alias', 'marko'))], + 'g_VXvid1X_propertyXcreatorCount_VXvid1X_inXcreatedX_countX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).as_('peter').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('knows').from_('marko').to(__.V().has('name', 'vadas')).add_e('knows').from_('marko').to('josh').add_e('created').from_('marko').to('lop').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple').add_e('created').from_('peter').to('lop')), (lambda g, vid1=None:g.V(vid1).property('creatorCount', __.V(vid1).in_('created').count())), (lambda g, vid1=None:g.V().has('creatorCount', long(3)))], + 'g_VXvid1X_propertyXknownCount_outXknowsX_countX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh')), (lambda g, vid1=None:g.V(vid1).property('knownCount', __.out('knows').count())), (lambda g, vid1=None:g.V().has('knownCount', long(2)))], + 'g_VXvid1X_propertyXcreator_inXcreatedX_valuesXnameXX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).as_('peter').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('knows').from_('marko').to(__.V().has('name', 'vadas')).add_e('knows').from_('marko').to('josh').add_e('created').from_('marko').to('lop').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple').add_e('created').from_('peter').to('lop')), (lambda g, vid1=None:g.V(vid1).property('creator', __.in_('created').values('name'))), (lambda g, vid1=None:g.V().has('creator'))], + 'g_VXvid2X_propertyXVXvid1X_projectXfriendCount_softwareCreatedXX': [(lambda g, vid2=None,vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).as_('peter').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh').add_e('created').from_('marko').to('lop').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple').add_e('created').from_('peter').to('lop')), (lambda g, vid2=None,vid1=None:g.V(vid2).property(__.V(vid1).project('friendCount', 'softwareCreated').by(__.out('knows').count()).by(__.out('created').values('name')))), (lambda g, vid2=None,vid1=None:g.V().has('friendCount', long(2))), (lambda g, vid2=None,vid1=None:g.V().has('softwareCreated', 'lop'))], + 'g_VXvid2X_propertyXVXvid1X_projectXoriginalName_originalLabelX_byXnameX_byXlabelXX': [(lambda g, vid2=None,vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java')), (lambda g, vid2=None,vid1=None:g.V(vid2).property(__.V(vid1).project('originalName', 'originalLabel').by(__.values('name')).by(__.label()))), (lambda g, vid2=None,vid1=None:g.V(vid2).has('originalName', 'marko')), (lambda g, vid2=None,vid1=None:g.V(vid2).has('originalLabel', 'person'))], + 'g_VXvid1X_propertyXlist_friends_outXknowsX_valuesXnameXX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh')), (lambda g, vid1=None:g.V(vid1).property(Cardinality.list_, 'friends', __.out('knows').values('name'))), (lambda g, vid1=None:g.V(vid1).properties('friends'))], + 'g_VXvid1X_propertyXset_langs_outXcreatedX_valuesXlangXX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple')), (lambda g, vid1=None:g.V(vid1).property(Cardinality.set_, 'langs', __.out('created').values('lang'))), (lambda g, vid1=None:g.V(vid1).properties('langs'))], + 'g_VXvid1X_propertyXsingle_friend_outXknowsX_valuesXnameXX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh')), (lambda g, vid1=None:g.V(vid1).property(Cardinality.single, 'friend', __.out('knows').values('name')))], + 'g_VXvid1X_propertyXVXvid1X_groupX_byXidX_byXvaluesXnameXXX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, vid1=None:g.V(vid1).property(__.V(vid1).group().by(__.id_()).by(__.values('name'))))], 'g_io_readXkryoX': [(lambda g:g.io('data/tinkerpop-modern.kryo').read()), (lambda g:g.V()), (lambda g:g.E())], 'g_io_read_withXreader_gryoX': [(lambda g:g.io('data/tinkerpop-modern.kryo').with_(IO.reader, IO.gryo).read()), (lambda g:g.V()), (lambda g:g.E())], 'g_io_readXgraphsonX': [(lambda g:g.io('data/tinkerpop-modern.json').read()), (lambda g:g.V()), (lambda g:g.E())], 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 f152691348e..ff0ad07295d 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 @@ -8422,6 +8422,533 @@ } ] }, + { + "scenario": "g_V_hasXname_constantXmarkoXX", + "traversals": [ + { + "original": "g.V().has(\"name\", __.constant(\"marko\"))", + "language": "g.V().has(\"name\", __.constant(\"marko\"))", + "canonical": "g.V().has(\"name\", __.constant(\"marko\"))", + "anonymized": "g.V().has(string0, __.constant(string1))", + "dotnet": "g.V().Has(\"name\", __.Constant(\"marko\"))", + "go": "g.V().Has(\"name\", gremlingo.T__.Constant(\"marko\"))", + "groovy": "g.V().has(\"name\", __.constant(\"marko\"))", + "java": "g.V().has(\"name\", __.constant(\"marko\"))", + "javascript": "g.V().has(\"name\", __.constant(\"marko\"))", + "python": "g.V().has('name', __.constant('marko'))" + } + ] + }, + { + "scenario": "g_V_hasXname_VXvid1X_outXknowsX_valuesXnameXX", + "traversals": [ + { + "original": "g.V().has(\"name\", __.V(vid1).out(\"knows\").values(\"name\").order())", + "language": "g.V().has(\"name\", __.V(vid1).out(\"knows\").values(\"name\").order())", + "canonical": "g.V().has(\"name\", __.V(vid1).out(\"knows\").values(\"name\").order())", + "anonymized": "g.V().has(string0, __.V(vid1).out(string1).values(string0).order())", + "dotnet": "g.V().Has(\"name\", __.V(vid1).Out(\"knows\").Values(\"name\").Order())", + "go": "g.V().Has(\"name\", gremlingo.T__.V(vid1).Out(\"knows\").Values(\"name\").Order())", + "groovy": "g.V().has(\"name\", __.V(vid1).out(\"knows\").values(\"name\").order())", + "java": "g.V().has(\"name\", __.V(vid1).out(\"knows\").values(\"name\").order())", + "javascript": "g.V().has(\"name\", __.V(vid1).out(\"knows\").values(\"name\").order())", + "python": "g.V().has('name', __.V(vid1).out('knows').values('name').order())" + } + ] + }, + { + "scenario": "g_V_hasXname_valuesXnonexistentXX", + "traversals": [ + { + "original": "g.V().has(\"name\", __.values(\"nonexistent\"))", + "language": "g.V().has(\"name\", __.values(\"nonexistent\"))", + "canonical": "g.V().has(\"name\", __.values(\"nonexistent\"))", + "anonymized": "g.V().has(string0, __.values(string1))", + "dotnet": "g.V().Has(\"name\", __.Values(\"nonexistent\"))", + "go": "g.V().Has(\"name\", gremlingo.T__.Values(\"nonexistent\"))", + "groovy": "g.V().has(\"name\", __.values(\"nonexistent\"))", + "java": "g.V().has(\"name\", __.values(\"nonexistent\"))", + "javascript": "g.V().has(\"name\", __.values(\"nonexistent\"))", + "python": "g.V().has('name', __.values('nonexistent'))" + } + ] + }, + { + "scenario": "g_V_hasXname_notXidentityXX", + "traversals": [ + { + "original": "g.V().has(\"name\", __.not(__.identity()))", + "language": "g.V().has(\"name\", __.not(__.identity()))", + "canonical": "g.V().has(\"name\", __.not(__.identity()))", + "anonymized": "g.V().has(string0, __.not(__.identity()))", + "dotnet": "g.V().Has(\"name\", __.Not(__.Identity()))", + "go": "g.V().Has(\"name\", gremlingo.T__.Not(gremlingo.T__.Identity()))", + "groovy": "g.V().has(\"name\", __.not(__.identity()))", + "java": "g.V().has(\"name\", __.not(__.identity()))", + "javascript": "g.V().has(\"name\", __.not(__.identity()))", + "python": "g.V().has('name', __.not_(__.identity()))" + } + ] + }, + { + "scenario": "g_V_hasXage_gtXconstantX29XXX", + "traversals": [ + { + "original": "g.V().has(\"age\", P.gt(__.constant(29)))", + "language": "g.V().has(\"age\", P.gt(__.constant(29)))", + "canonical": "g.V().has(\"age\", P.gt(__.constant(29)))", + "anonymized": "g.V().has(string0, P.gt(__.constant(number0)))", + "dotnet": "g.V().Has(\"age\", P.Gt(__.Constant(29)))", + "go": "g.V().Has(\"age\", gremlingo.P.Gt(gremlingo.T__.Constant(29)))", + "groovy": "g.V().has(\"age\", P.gt(__.constant(29)))", + "java": "g.V().has(\"age\", P.gt(__.constant(29)))", + "javascript": "g.V().has(\"age\", P.gt(__.constant(29)))", + "python": "g.V().has('age', P.gt(__.constant(29)))" + } + ] + }, + { + "scenario": "g_V_hasXage_lteXconstantX27XXX", + "traversals": [ + { + "original": "g.V().has(\"age\", P.lte(__.constant(27)))", + "language": "g.V().has(\"age\", P.lte(__.constant(27)))", + "canonical": "g.V().has(\"age\", P.lte(__.constant(27)))", + "anonymized": "g.V().has(string0, P.lte(__.constant(number0)))", + "dotnet": "g.V().Has(\"age\", P.Lte(__.Constant(27)))", + "go": "g.V().Has(\"age\", gremlingo.P.Lte(gremlingo.T__.Constant(27)))", + "groovy": "g.V().has(\"age\", P.lte(__.constant(27)))", + "java": "g.V().has(\"age\", P.lte(__.constant(27)))", + "javascript": "g.V().has(\"age\", P.lte(__.constant(27)))", + "python": "g.V().has('age', P.lte(__.constant(27)))" + } + ] + }, + { + "scenario": "g_V_hasXage_neqXconstantX32XXX", + "traversals": [ + { + "original": "g.V().has(\"age\", P.neq(__.constant(32)))", + "language": "g.V().has(\"age\", P.neq(__.constant(32)))", + "canonical": "g.V().has(\"age\", P.neq(__.constant(32)))", + "anonymized": "g.V().has(string0, P.neq(__.constant(number0)))", + "dotnet": "g.V().Has(\"age\", P.Neq(__.Constant(32)))", + "go": "g.V().Has(\"age\", gremlingo.P.Neq(gremlingo.T__.Constant(32)))", + "groovy": "g.V().has(\"age\", P.neq(__.constant(32)))", + "java": "g.V().has(\"age\", P.neq(__.constant(32)))", + "javascript": "g.V().has(\"age\", P.neq(__.constant(32)))", + "python": "g.V().has('age', P.neq(__.constant(32)))" + } + ] + }, + { + "scenario": "g_V_hasXname_eqXconstantXmarkoXXX", + "traversals": [ + { + "original": "g.V().has(\"name\", P.eq(__.constant(\"marko\")))", + "language": "g.V().has(\"name\", P.eq(__.constant(\"marko\")))", + "canonical": "g.V().has(\"name\", P.eq(__.constant(\"marko\")))", + "anonymized": "g.V().has(string0, P.eq(__.constant(string1)))", + "dotnet": "g.V().Has(\"name\", P.Eq(__.Constant(\"marko\")))", + "go": "g.V().Has(\"name\", gremlingo.P.Eq(gremlingo.T__.Constant(\"marko\")))", + "groovy": "g.V().has(\"name\", P.eq(__.constant(\"marko\")))", + "java": "g.V().has(\"name\", P.eq(__.constant(\"marko\")))", + "javascript": "g.V().has(\"name\", P.eq(__.constant(\"marko\")))", + "python": "g.V().has('name', P.eq(__.constant('marko')))" + } + ] + }, + { + "scenario": "g_V_hasXage_ltXconstantX29XXX", + "traversals": [ + { + "original": "g.V().has(\"age\", P.lt(__.constant(29)))", + "language": "g.V().has(\"age\", P.lt(__.constant(29)))", + "canonical": "g.V().has(\"age\", P.lt(__.constant(29)))", + "anonymized": "g.V().has(string0, P.lt(__.constant(number0)))", + "dotnet": "g.V().Has(\"age\", P.Lt(__.Constant(29)))", + "go": "g.V().Has(\"age\", gremlingo.P.Lt(gremlingo.T__.Constant(29)))", + "groovy": "g.V().has(\"age\", P.lt(__.constant(29)))", + "java": "g.V().has(\"age\", P.lt(__.constant(29)))", + "javascript": "g.V().has(\"age\", P.lt(__.constant(29)))", + "python": "g.V().has('age', P.lt(__.constant(29)))" + } + ] + }, + { + "scenario": "g_V_hasXage_gteXconstantX32XXX", + "traversals": [ + { + "original": "g.V().has(\"age\", P.gte(__.constant(32)))", + "language": "g.V().has(\"age\", P.gte(__.constant(32)))", + "canonical": "g.V().has(\"age\", P.gte(__.constant(32)))", + "anonymized": "g.V().has(string0, P.gte(__.constant(number0)))", + "dotnet": "g.V().Has(\"age\", P.Gte(__.Constant(32)))", + "go": "g.V().Has(\"age\", gremlingo.P.Gte(gremlingo.T__.Constant(32)))", + "groovy": "g.V().has(\"age\", P.gte(__.constant(32)))", + "java": "g.V().has(\"age\", P.gte(__.constant(32)))", + "javascript": "g.V().has(\"age\", P.gte(__.constant(32)))", + "python": "g.V().has('age', P.gte(__.constant(32)))" + } + ] + }, + { + "scenario": "g_V_hasXage_eqXvaluesXnonexistentXXX", + "traversals": [ + { + "original": "g.V().has(\"age\", P.eq(__.values(\"nonexistent\")))", + "language": "g.V().has(\"age\", P.eq(__.values(\"nonexistent\")))", + "canonical": "g.V().has(\"age\", P.eq(__.values(\"nonexistent\")))", + "anonymized": "g.V().has(string0, P.eq(__.values(string1)))", + "dotnet": "g.V().Has(\"age\", P.Eq(__.Values(\"nonexistent\")))", + "go": "g.V().Has(\"age\", gremlingo.P.Eq(gremlingo.T__.Values(\"nonexistent\")))", + "groovy": "g.V().has(\"age\", P.eq(__.values(\"nonexistent\")))", + "java": "g.V().has(\"age\", P.eq(__.values(\"nonexistent\")))", + "javascript": "g.V().has(\"age\", P.eq(__.values(\"nonexistent\")))", + "python": "g.V().has('age', P.eq(__.values('nonexistent')))" + } + ] + }, + { + "scenario": "g_V_hasXlabel_constantXpersonXX", + "traversals": [ + { + "original": "g.V().has(T.label, __.constant(\"person\"))", + "language": "g.V().has(T.label, __.constant(\"person\"))", + "canonical": "g.V().has(T.label, __.constant(\"person\"))", + "anonymized": "g.V().has(T.label, __.constant(string0))", + "dotnet": "g.V().Has(T.Label, __.Constant(\"person\"))", + "go": "g.V().Has(gremlingo.T.Label, gremlingo.T__.Constant(\"person\"))", + "groovy": "g.V().has(T.label, __.constant(\"person\"))", + "java": "g.V().has(T.label, __.constant(\"person\"))", + "javascript": "g.V().has(T.label, __.constant(\"person\"))", + "python": "g.V().has(T.label, __.constant('person'))" + } + ] + }, + { + "scenario": "g_V_hasXperson_name_constantXmarkoXX_age", + "traversals": [ + { + "original": "g.V().has(\"person\", \"name\", __.constant(\"marko\")).values(\"age\")", + "language": "g.V().has(\"person\", \"name\", __.constant(\"marko\")).values(\"age\")", + "canonical": "g.V().has(\"person\", \"name\", __.constant(\"marko\")).values(\"age\")", + "anonymized": "g.V().has(string0, string1, __.constant(string2)).values(string3)", + "dotnet": "g.V().Has(\"person\", \"name\", __.Constant(\"marko\")).Values(\"age\")", + "go": "g.V().Has(\"person\", \"name\", gremlingo.T__.Constant(\"marko\")).Values(\"age\")", + "groovy": "g.V().has(\"person\", \"name\", __.constant(\"marko\")).values(\"age\")", + "java": "g.V().has(\"person\", \"name\", __.constant(\"marko\")).values(\"age\")", + "javascript": "g.V().has(\"person\", \"name\", __.constant(\"marko\")).values(\"age\")", + "python": "g.V().has('person', 'name', __.constant('marko')).values('age')" + } + ] + }, + { + "scenario": "g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_constantXpeterXX_foldXX", + "traversals": [ + { + "original": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.constant(\"peter\")).fold()))", + "language": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.constant(\"peter\")).fold()))", + "canonical": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.constant(\"peter\")).fold()))", + "anonymized": "g.V().has(string0, P.within(__.union(__.V(vid1).out(string1).values(string0), __.constant(string2)).fold()))", + "dotnet": "g.V().Has(\"name\", P.Within(__.Union(__.V(vid1).Out(\"knows\").Values(\"name\"), __.Constant(\"peter\")).Fold()))", + "go": "g.V().Has(\"name\", gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V(vid1).Out(\"knows\").Values(\"name\"), gremlingo.T__.Constant(\"peter\")).Fold()))", + "groovy": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.constant(\"peter\")).fold()))", + "java": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.constant(\"peter\")).fold()))", + "javascript": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.constant(\"peter\")).fold()))", + "python": "g.V().has('name', P.within(__.union(__.V(vid1).out('knows').values('name'), __.constant('peter')).fold()))" + } + ] + }, + { + "scenario": "g_V_hasXname_withinXvaluesXnonexistentX_constantXmarkoXXX", + "traversals": [ + { + "original": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.constant(\"marko\")))", + "language": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.constant(\"marko\")))", + "canonical": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.constant(\"marko\")))", + "anonymized": "g.V().has(string0, P.within(__.values(string1), __.constant(string2)))", + "dotnet": "g.V().Has(\"name\", P.Within(__.Values(\"nonexistent\"), __.Constant(\"marko\")))", + "go": "g.V().Has(\"name\", gremlingo.P.Within(gremlingo.T__.Values(\"nonexistent\"), gremlingo.T__.Constant(\"marko\")))", + "groovy": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.constant(\"marko\")))", + "java": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.constant(\"marko\")))", + "javascript": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.constant(\"marko\")))", + "python": "g.V().has('name', P.within(__.values('nonexistent'), __.constant('marko')))" + } + ] + }, + { + "scenario": "g_V_hasXname_withinXvaluesXnonexistentX_valuesXnonexistent2XXX", + "traversals": [ + { + "original": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.values(\"nonexistent2\")))", + "language": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.values(\"nonexistent2\")))", + "canonical": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.values(\"nonexistent2\")))", + "anonymized": "g.V().has(string0, P.within(__.values(string1), __.values(string2)))", + "dotnet": "g.V().Has(\"name\", P.Within(__.Values(\"nonexistent\"), __.Values(\"nonexistent2\")))", + "go": "g.V().Has(\"name\", gremlingo.P.Within(gremlingo.T__.Values(\"nonexistent\"), gremlingo.T__.Values(\"nonexistent2\")))", + "groovy": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.values(\"nonexistent2\")))", + "java": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.values(\"nonexistent2\")))", + "javascript": "g.V().has(\"name\", P.within(__.values(\"nonexistent\"), __.values(\"nonexistent2\")))", + "python": "g.V().has('name', P.within(__.values('nonexistent'), __.values('nonexistent2')))" + } + ] + }, + { + "scenario": "g_V_hasXname_withoutXconstantXmarkoX_constantXvadasX_constantXpeterXXX", + "traversals": [ + { + "original": "g.V().has(\"name\", P.without(__.constant(\"marko\"), __.constant(\"vadas\"), __.constant(\"peter\")))", + "language": "g.V().has(\"name\", P.without(__.constant(\"marko\"), __.constant(\"vadas\"), __.constant(\"peter\")))", + "canonical": "g.V().has(\"name\", P.without(__.constant(\"marko\"), __.constant(\"vadas\"), __.constant(\"peter\")))", + "anonymized": "g.V().has(string0, P.without(__.constant(string1), __.constant(string2), __.constant(string3)))", + "dotnet": "g.V().Has(\"name\", P.Without(__.Constant(\"marko\"), __.Constant(\"vadas\"), __.Constant(\"peter\")))", + "go": "g.V().Has(\"name\", gremlingo.P.Without(gremlingo.T__.Constant(\"marko\"), gremlingo.T__.Constant(\"vadas\"), gremlingo.T__.Constant(\"peter\")))", + "groovy": "g.V().has(\"name\", P.without(__.constant(\"marko\"), __.constant(\"vadas\"), __.constant(\"peter\")))", + "java": "g.V().has(\"name\", P.without(__.constant(\"marko\"), __.constant(\"vadas\"), __.constant(\"peter\")))", + "javascript": "g.V().has(\"name\", P.without(__.constant(\"marko\"), __.constant(\"vadas\"), __.constant(\"peter\")))", + "python": "g.V().has('name', P.without(__.constant('marko'), __.constant('vadas'), __.constant('peter')))" + } + ] + }, + { + "scenario": "g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_VXvid3X_outXcreatedX_valuesXnameXX_foldXX", + "traversals": [ + { + "original": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"),__.V(vid3).out(\"created\").values(\"name\")).fold()))", + "language": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.V(vid3).out(\"created\").values(\"name\")).fold()))", + "canonical": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.V(vid3).out(\"created\").values(\"name\")).fold()))", + "anonymized": "g.V().has(string0, P.within(__.union(__.V(vid1).out(string1).values(string0), __.V(vid3).out(string2).values(string0)).fold()))", + "dotnet": "g.V().Has(\"name\", P.Within(__.Union(__.V(vid1).Out(\"knows\").Values(\"name\"), __.V(vid3).Out(\"created\").Values(\"name\")).Fold()))", + "go": "g.V().Has(\"name\", gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V(vid1).Out(\"knows\").Values(\"name\"), gremlingo.T__.V(vid3).Out(\"created\").Values(\"name\")).Fold()))", + "groovy": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.V(vid3).out(\"created\").values(\"name\")).fold()))", + "java": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.V(vid3).out(\"created\").values(\"name\")).fold()))", + "javascript": "g.V().has(\"name\", P.within(__.union(__.V(vid1).out(\"knows\").values(\"name\"), __.V(vid3).out(\"created\").values(\"name\")).fold()))", + "python": "g.V().has('name', P.within(__.union(__.V(vid1).out('knows').values('name'), __.V(vid3).out('created').values('name')).fold()))" + } + ] + }, + { + "scenario": "g_V_hasLabelXsoftwareX_hasXname_withoutXunionXVXvid1X_outXcreatedX_valuesXnameX_VXvid4X_outXcreatedX_valuesXnameXX_foldXX", + "traversals": [ + { + "original": "g.V().hasLabel(\"software\").has(\"name\", P.without(__.union(__.V(vid1).out(\"created\").values(\"name\"),__.V(vid4).out(\"created\").values(\"name\")).fold()))", + "language": "g.V().hasLabel(\"software\").has(\"name\", P.without(__.union(__.V(vid1).out(\"created\").values(\"name\"), __.V(vid4).out(\"created\").values(\"name\")).fold()))", + "canonical": "g.V().hasLabel(\"software\").has(\"name\", P.without(__.union(__.V(vid1).out(\"created\").values(\"name\"), __.V(vid4).out(\"created\").values(\"name\")).fold()))", + "anonymized": "g.V().hasLabel(string0).has(string1, P.without(__.union(__.V(vid1).out(string2).values(string1), __.V(vid4).out(string2).values(string1)).fold()))", + "dotnet": "g.V().HasLabel(\"software\").Has(\"name\", P.Without(__.Union(__.V(vid1).Out(\"created\").Values(\"name\"), __.V(vid4).Out(\"created\").Values(\"name\")).Fold()))", + "go": "g.V().HasLabel(\"software\").Has(\"name\", gremlingo.P.Without(gremlingo.T__.Union(gremlingo.T__.V(vid1).Out(\"created\").Values(\"name\"), gremlingo.T__.V(vid4).Out(\"created\").Values(\"name\")).Fold()))", + "groovy": "g.V().hasLabel(\"software\").has(\"name\", P.without(__.union(__.V(vid1).out(\"created\").values(\"name\"), __.V(vid4).out(\"created\").values(\"name\")).fold()))", + "java": "g.V().hasLabel(\"software\").has(\"name\", P.without(__.union(__.V(vid1).out(\"created\").values(\"name\"), __.V(vid4).out(\"created\").values(\"name\")).fold()))", + "javascript": "g.V().hasLabel(\"software\").has(\"name\", P.without(__.union(__.V(vid1).out(\"created\").values(\"name\"), __.V(vid4).out(\"created\").values(\"name\")).fold()))", + "python": "g.V().has_label('software').has('name', P.without(__.union(__.V(vid1).out('created').values('name'), __.V(vid4).out('created').values('name')).fold()))" + } + ] + }, + { + "scenario": "g_V_hasLabelXpersonX_valuesXageX_isXwithinXunionXVXvid1X_valuesXageX_V_hasXname_lopX_inXcreatedX_valuesXageXX_foldXX", + "traversals": [ + { + "original": "g.V().hasLabel(\"person\").values(\"age\").is(P.within(__.union(__.V(vid1).values(\"age\"),__.V().has(\"name\",\"lop\").in(\"created\").values(\"age\")).fold()))", + "language": "g.V().hasLabel(\"person\").values(\"age\").is(P.within(__.union(__.V(vid1).values(\"age\"), __.V().has(\"name\", \"lop\").in(\"created\").values(\"age\")).fold()))", + "canonical": "g.V().hasLabel(\"person\").values(\"age\").is(P.within(__.union(__.V(vid1).values(\"age\"), __.V().has(\"name\", \"lop\").in(\"created\").values(\"age\")).fold()))", + "anonymized": "g.V().hasLabel(string0).values(string1).is(P.within(__.union(__.V(vid1).values(string1), __.V().has(string2, string3).in(string4).values(string1)).fold()))", + "dotnet": "g.V().HasLabel(\"person\").Values(\"age\").Is(P.Within(__.Union(__.V(vid1).Values(\"age\"), __.V().Has(\"name\", \"lop\").In(\"created\").Values(\"age\")).Fold()))", + "go": "g.V().HasLabel(\"person\").Values(\"age\").Is(gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V(vid1).Values(\"age\"), gremlingo.T__.V().Has(\"name\", \"lop\").In(\"created\").Values(\"age\")).Fold()))", + "groovy": "g.V().hasLabel(\"person\").values(\"age\").is(P.within(__.union(__.V(vid1).values(\"age\"), __.V().has(\"name\", \"lop\").in(\"created\").values(\"age\")).fold()))", + "java": "g.V().hasLabel(\"person\").values(\"age\").is(P.within(__.union(__.V(vid1).values(\"age\"), __.V().has(\"name\", \"lop\").in(\"created\").values(\"age\")).fold()))", + "javascript": "g.V().hasLabel(\"person\").values(\"age\").is(P.within(__.union(__.V(vid1).values(\"age\"), __.V().has(\"name\", \"lop\").in_(\"created\").values(\"age\")).fold()))", + "python": "g.V().has_label('person').values('age').is_(P.within(__.union(__.V(vid1).values('age'), __.V().has('name', 'lop').in_('created').values('age')).fold()))" + } + ] + }, + { + "scenario": "g_VXvid1X_outEXknowsX_filterXinV_hasXname_withinXunionXV_hasXname_lopX_inXcreatedX_valuesXnameX_V_hasXname_rippleX_inXcreatedX_valuesXnameXX_foldXXXX", + "traversals": [ + { + "original": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", P.within(__.union(__.V().has(\"name\",\"lop\").in(\"created\").values(\"name\"),__.V().has(\"name\",\"ripple\").in(\"created\").values(\"name\")).fold())))", + "language": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", P.within(__.union(__.V().has(\"name\", \"lop\").in(\"created\").values(\"name\"), __.V().has(\"name\", \"ripple\").in(\"created\").values(\"name\")).fold())))", + "canonical": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", P.within(__.union(__.V().has(\"name\", \"lop\").in(\"created\").values(\"name\"), __.V().has(\"name\", \"ripple\").in(\"created\").values(\"name\")).fold())))", + "anonymized": "g.V(vid1).outE(string0).filter(__.inV().has(string1, P.within(__.union(__.V().has(string1, string2).in(string3).values(string1), __.V().has(string1, string4).in(string3).values(string1)).fold())))", + "dotnet": "g.V(vid1).OutE(\"knows\").Filter(__.InV().Has(\"name\", P.Within(__.Union(__.V().Has(\"name\", \"lop\").In(\"created\").Values(\"name\"), __.V().Has(\"name\", \"ripple\").In(\"created\").Values(\"name\")).Fold())))", + "go": "g.V(vid1).OutE(\"knows\").Filter(gremlingo.T__.InV().Has(\"name\", gremlingo.P.Within(gremlingo.T__.Union(gremlingo.T__.V().Has(\"name\", \"lop\").In(\"created\").Values(\"name\"), gremlingo.T__.V().Has(\"name\", \"ripple\").In(\"created\").Values(\"name\")).Fold())))", + "groovy": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", P.within(__.union(__.V().has(\"name\", \"lop\").in(\"created\").values(\"name\"), __.V().has(\"name\", \"ripple\").in(\"created\").values(\"name\")).fold())))", + "java": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", P.within(__.union(__.V().has(\"name\", \"lop\").in(\"created\").values(\"name\"), __.V().has(\"name\", \"ripple\").in(\"created\").values(\"name\")).fold())))", + "javascript": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", P.within(__.union(__.V().has(\"name\", \"lop\").in_(\"created\").values(\"name\"), __.V().has(\"name\", \"ripple\").in_(\"created\").values(\"name\")).fold())))", + "python": "g.V(vid1).out_e('knows').filter_(__.in_v().has('name', P.within(__.union(__.V().has('name', 'lop').in_('created').values('name'), __.V().has('name', 'ripple').in_('created').values('name')).fold())))" + } + ] + }, + { + "scenario": "g_V_hasLabelXconstantXpersonXX", + "traversals": [ + { + "original": "g.V().hasLabel(__.constant(\"person\"))", + "language": "g.V().hasLabel(__.constant(\"person\"))", + "canonical": "g.V().hasLabel(__.constant(\"person\"))", + "anonymized": "g.V().hasLabel(__.constant(string0))", + "dotnet": "g.V().HasLabel(__.Constant(\"person\"))", + "go": "g.V().HasLabel(gremlingo.T__.Constant(\"person\"))", + "groovy": "g.V().hasLabel(__.constant(\"person\"))", + "java": "g.V().hasLabel(__.constant(\"person\"))", + "javascript": "g.V().hasLabel(__.constant(\"person\"))", + "python": "g.V().has_label(__.constant('person'))" + } + ] + }, + { + "scenario": "g_V_hasIdXeqXVXvid1X_idXX", + "traversals": [ + { + "original": "g.V().hasId(P.eq(__.V(vid1).id()))", + "language": "g.V().hasId(P.eq(__.V(vid1).id()))", + "canonical": "g.V().hasId(P.eq(__.V(vid1).id()))", + "anonymized": "g.V().hasId(P.eq(__.V(vid1).id()))", + "dotnet": "g.V().HasId(P.Eq(__.V(vid1).Id()))", + "go": "g.V().HasId(gremlingo.P.Eq(gremlingo.T__.V(vid1).Id()))", + "groovy": "g.V().hasId(P.eq(__.V(vid1).id()))", + "java": "g.V().hasId(P.eq(__.V(vid1).id()))", + "javascript": "g.V().hasId(P.eq(__.V(vid1).id()))", + "python": "g.V().has_id(P.eq(__.V(vid1).id_()))" + } + ] + }, + { + "scenario": "g_V_hasIdXVXvid1X_idXX", + "traversals": [ + { + "original": "g.V().hasId(__.V(vid1).id())", + "language": "g.V().hasId(__.V(vid1).id())", + "canonical": "g.V().hasId(__.V(vid1).id())", + "anonymized": "g.V().hasId(__.V(vid1).id())", + "dotnet": "g.V().HasId(__.V(vid1).Id())", + "go": "g.V().HasId(gremlingo.T__.V(vid1).Id())", + "groovy": "g.V().hasId(__.V(vid1).id())", + "java": "g.V().hasId(__.V(vid1).id())", + "javascript": "g.V().hasId(__.V(vid1).id())", + "python": "g.V().has_id(__.V(vid1).id_())" + } + ] + }, + { + "scenario": "g_V_propertiesXageX_hasKeyXconstantXageXX", + "traversals": [ + { + "original": "g.V().properties(\"age\").hasKey(__.constant(\"age\"))", + "language": "g.V().properties(\"age\").hasKey(__.constant(\"age\"))", + "canonical": "g.V().properties(\"age\").hasKey(__.constant(\"age\"))", + "anonymized": "g.V().properties(string0).hasKey(__.constant(string0))", + "dotnet": "g.V().Properties(\"age\").HasKey(__.Constant(\"age\"))", + "go": "g.V().Properties(\"age\").HasKey(gremlingo.T__.Constant(\"age\"))", + "groovy": "g.V().properties(\"age\").hasKey(__.constant(\"age\"))", + "java": "g.V().properties(\"age\").hasKey(__.constant(\"age\"))", + "javascript": "g.V().properties(\"age\").hasKey(__.constant(\"age\"))", + "python": "g.V().properties('age').has_key(__.constant('age'))" + } + ] + }, + { + "scenario": "g_V_propertiesXageX_hasKeyXeqXconstantXageXXX", + "traversals": [ + { + "original": "g.V().properties(\"age\").hasKey(P.eq(__.constant(\"age\")))", + "language": "g.V().properties(\"age\").hasKey(P.eq(__.constant(\"age\")))", + "canonical": "g.V().properties(\"age\").hasKey(P.eq(__.constant(\"age\")))", + "anonymized": "g.V().properties(string0).hasKey(P.eq(__.constant(string0)))", + "dotnet": "g.V().Properties(\"age\").HasKey(P.Eq(__.Constant(\"age\")))", + "go": "g.V().Properties(\"age\").HasKey(gremlingo.P.Eq(gremlingo.T__.Constant(\"age\")))", + "groovy": "g.V().properties(\"age\").hasKey(P.eq(__.constant(\"age\")))", + "java": "g.V().properties(\"age\").hasKey(P.eq(__.constant(\"age\")))", + "javascript": "g.V().properties(\"age\").hasKey(P.eq(__.constant(\"age\")))", + "python": "g.V().properties('age').has_key(P.eq(__.constant('age')))" + } + ] + }, + { + "scenario": "g_V_propertiesXageX_hasValueXconstantX29XX", + "traversals": [ + { + "original": "g.V().properties(\"age\").hasValue(__.constant(29))", + "language": "g.V().properties(\"age\").hasValue(__.constant(29))", + "canonical": "g.V().properties(\"age\").hasValue(__.constant(29))", + "anonymized": "g.V().properties(string0).hasValue(__.constant(number0))", + "dotnet": "g.V().Properties(\"age\").HasValue(__.Constant(29))", + "go": "g.V().Properties(\"age\").HasValue(gremlingo.T__.Constant(29))", + "groovy": "g.V().properties(\"age\").hasValue(__.constant(29))", + "java": "g.V().properties(\"age\").hasValue(__.constant(29))", + "javascript": "g.V().properties(\"age\").hasValue(__.constant(29))", + "python": "g.V().properties('age').has_value(__.constant(29))" + } + ] + }, + { + "scenario": "g_V_propertiesXageX_hasValueXeqXconstantX29XXX", + "traversals": [ + { + "original": "g.V().properties(\"age\").hasValue(P.eq(__.constant(29)))", + "language": "g.V().properties(\"age\").hasValue(P.eq(__.constant(29)))", + "canonical": "g.V().properties(\"age\").hasValue(P.eq(__.constant(29)))", + "anonymized": "g.V().properties(string0).hasValue(P.eq(__.constant(number0)))", + "dotnet": "g.V().Properties(\"age\").HasValue(P.Eq(__.Constant(29)))", + "go": "g.V().Properties(\"age\").HasValue(gremlingo.P.Eq(gremlingo.T__.Constant(29)))", + "groovy": "g.V().properties(\"age\").hasValue(P.eq(__.constant(29)))", + "java": "g.V().properties(\"age\").hasValue(P.eq(__.constant(29)))", + "javascript": "g.V().properties(\"age\").hasValue(P.eq(__.constant(29)))", + "python": "g.V().properties('age').has_value(P.eq(__.constant(29)))" + } + ] + }, + { + "scenario": "g_VXvid1X_asXaX_V_hasXage_gtXselectXaX_valuesXageXXX_valuesXnameX", + "traversals": [ + { + "original": "g.V(vid1).as(\"a\").V().has(\"age\", P.gt(__.select(\"a\").values(\"age\"))).values(\"name\")", + "language": "g.V(vid1).as(\"a\").V().has(\"age\", P.gt(__.select(\"a\").values(\"age\"))).values(\"name\")", + "canonical": "g.V(vid1).as(\"a\").V().has(\"age\", P.gt(__.select(\"a\").values(\"age\"))).values(\"name\")", + "anonymized": "g.V(vid1).as(string0).V().has(string1, P.gt(__.select(string0).values(string1))).values(string2)", + "dotnet": "g.V(vid1).As(\"a\").V().Has(\"age\", P.Gt(__.Select(\"a\").Values(\"age\"))).Values(\"name\")", + "go": "g.V(vid1).As(\"a\").V().Has(\"age\", gremlingo.P.Gt(gremlingo.T__.Select(\"a\").Values(\"age\"))).Values(\"name\")", + "groovy": "g.V(vid1).as(\"a\").V().has(\"age\", P.gt(__.select(\"a\").values(\"age\"))).values(\"name\")", + "java": "g.V(vid1).as(\"a\").V().has(\"age\", P.gt(__.select(\"a\").values(\"age\"))).values(\"name\")", + "javascript": "g.V(vid1).as(\"a\").V().has(\"age\", P.gt(__.select(\"a\").values(\"age\"))).values(\"name\")", + "python": "g.V(vid1).as_('a').V().has('age', P.gt(__.select('a').values('age'))).values('name')" + } + ] + }, + { + "scenario": "g_withSackX29X_V_hasXage_gtXsackXX_valuesXnameX", + "traversals": [ + { + "original": "g.withSack(29).V().has(\"age\", P.gt(__.sack())).values(\"name\")", + "language": "g.withSack(29).V().has(\"age\", P.gt(__.sack())).values(\"name\")", + "canonical": "g.withSack(29).V().has(\"age\", P.gt(__.sack())).values(\"name\")", + "anonymized": "g.withSack(number0).V().has(string0, P.gt(__.sack())).values(string1)", + "dotnet": "g.WithSack(29).V().Has(\"age\", P.Gt(__.Sack())).Values(\"name\")", + "go": "g.WithSack(29).V().Has(\"age\", gremlingo.P.Gt(gremlingo.T__.Sack())).Values(\"name\")", + "groovy": "g.withSack(29).V().has(\"age\", P.gt(__.sack())).values(\"name\")", + "java": "g.withSack(29).V().has(\"age\", P.gt(__.sack())).values(\"name\")", + "javascript": "g.withSack(29).V().has(\"age\", P.gt(__.sack())).values(\"name\")", + "python": "g.with_sack(29).V().has('age', P.gt(__.sack())).values('name')" + } + ] + }, + { + "scenario": "g_V_hasXname_markoX_outEXknowsX_hasXweight_gteXconstantX05XXX", + "traversals": [ + { + "original": "g.V().has(\"name\",\"marko\").outE(\"knows\").has(\"weight\", P.gte(__.constant(0.5)))", + "language": "g.V().has(\"name\", \"marko\").outE(\"knows\").has(\"weight\", P.gte(__.constant(0.5)))", + "canonical": "g.V().has(\"name\", \"marko\").outE(\"knows\").has(\"weight\", P.gte(__.constant(0.5)))", + "anonymized": "g.V().has(string0, string1).outE(string2).has(string3, P.gte(__.constant(number0)))", + "dotnet": "g.V().Has(\"name\", \"marko\").OutE(\"knows\").Has(\"weight\", P.Gte(__.Constant(0.5)))", + "go": "g.V().Has(\"name\", \"marko\").OutE(\"knows\").Has(\"weight\", gremlingo.P.Gte(gremlingo.T__.Constant(0.5)))", + "groovy": "g.V().has(\"name\", \"marko\").outE(\"knows\").has(\"weight\", P.gte(__.constant(0.5)))", + "java": "g.V().has(\"name\", \"marko\").outE(\"knows\").has(\"weight\", P.gte(__.constant(0.5)))", + "javascript": "g.V().has(\"name\", \"marko\").outE(\"knows\").has(\"weight\", P.gte(__.constant(0.5)))", + "python": "g.V().has('name', 'marko').out_e('knows').has('weight', P.gte(__.constant(0.5)))" + } + ] + }, { "scenario": "g_V_hasIdXemptyX_count", "traversals": [ @@ -9449,6 +9976,380 @@ } ] }, + { + "scenario": "g_V_valuesXageX_isXconstantX29XX", + "traversals": [ + { + "original": "g.V().values(\"age\").is(__.constant(29))", + "language": "g.V().values(\"age\").is(__.constant(29))", + "canonical": "g.V().values(\"age\").is(__.constant(29))", + "anonymized": "g.V().values(string0).is(__.constant(number0))", + "dotnet": "g.V().Values(\"age\").Is(__.Constant(29))", + "go": "g.V().Values(\"age\").Is(gremlingo.T__.Constant(29))", + "groovy": "g.V().values(\"age\").is(__.constant(29))", + "java": "g.V().values(\"age\").is(__.constant(29))", + "javascript": "g.V().values(\"age\").is(__.constant(29))", + "python": "g.V().values('age').is_(__.constant(29))" + } + ] + }, + { + "scenario": "g_V_valuesXnameX_isXconstantXmarkoXX", + "traversals": [ + { + "original": "g.V().values(\"name\").is(__.constant(\"marko\"))", + "language": "g.V().values(\"name\").is(__.constant(\"marko\"))", + "canonical": "g.V().values(\"name\").is(__.constant(\"marko\"))", + "anonymized": "g.V().values(string0).is(__.constant(string1))", + "dotnet": "g.V().Values(\"name\").Is(__.Constant(\"marko\"))", + "go": "g.V().Values(\"name\").Is(gremlingo.T__.Constant(\"marko\"))", + "groovy": "g.V().values(\"name\").is(__.constant(\"marko\"))", + "java": "g.V().values(\"name\").is(__.constant(\"marko\"))", + "javascript": "g.V().values(\"name\").is(__.constant(\"marko\"))", + "python": "g.V().values('name').is_(__.constant('marko'))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXgtXconstantX29XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").is(P.gt(__.constant(29)))", + "language": "g.V().values(\"age\").is(P.gt(__.constant(29)))", + "canonical": "g.V().values(\"age\").is(P.gt(__.constant(29)))", + "anonymized": "g.V().values(string0).is(P.gt(__.constant(number0)))", + "dotnet": "g.V().Values(\"age\").Is(P.Gt(__.Constant(29)))", + "go": "g.V().Values(\"age\").Is(gremlingo.P.Gt(gremlingo.T__.Constant(29)))", + "groovy": "g.V().values(\"age\").is(P.gt(__.constant(29)))", + "java": "g.V().values(\"age\").is(P.gt(__.constant(29)))", + "javascript": "g.V().values(\"age\").is(P.gt(__.constant(29)))", + "python": "g.V().values('age').is_(P.gt(__.constant(29)))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXltXconstantX32XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").is(P.lt(__.constant(32)))", + "language": "g.V().values(\"age\").is(P.lt(__.constant(32)))", + "canonical": "g.V().values(\"age\").is(P.lt(__.constant(32)))", + "anonymized": "g.V().values(string0).is(P.lt(__.constant(number0)))", + "dotnet": "g.V().Values(\"age\").Is(P.Lt(__.Constant(32)))", + "go": "g.V().Values(\"age\").Is(gremlingo.P.Lt(gremlingo.T__.Constant(32)))", + "groovy": "g.V().values(\"age\").is(P.lt(__.constant(32)))", + "java": "g.V().values(\"age\").is(P.lt(__.constant(32)))", + "javascript": "g.V().values(\"age\").is(P.lt(__.constant(32)))", + "python": "g.V().values('age').is_(P.lt(__.constant(32)))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXneqXconstantX35XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").is(P.neq(__.constant(35)))", + "language": "g.V().values(\"age\").is(P.neq(__.constant(35)))", + "canonical": "g.V().values(\"age\").is(P.neq(__.constant(35)))", + "anonymized": "g.V().values(string0).is(P.neq(__.constant(number0)))", + "dotnet": "g.V().Values(\"age\").Is(P.Neq(__.Constant(35)))", + "go": "g.V().Values(\"age\").Is(gremlingo.P.Neq(gremlingo.T__.Constant(35)))", + "groovy": "g.V().values(\"age\").is(P.neq(__.constant(35)))", + "java": "g.V().values(\"age\").is(P.neq(__.constant(35)))", + "javascript": "g.V().values(\"age\").is(P.neq(__.constant(35)))", + "python": "g.V().values('age').is_(P.neq(__.constant(35)))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXwithinXVXvid1X_outXknowsX_valuesXageXXX", + "traversals": [ + { + "original": "g.V().values(\"age\").is(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "language": "g.V().values(\"age\").is(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "canonical": "g.V().values(\"age\").is(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "anonymized": "g.V().values(string0).is(P.within(__.V(vid1).out(string1).values(string0).fold()))", + "dotnet": "g.V().Values(\"age\").Is(P.Within(__.V(vid1).Out(\"knows\").Values(\"age\").Fold()))", + "go": "g.V().Values(\"age\").Is(gremlingo.P.Within(gremlingo.T__.V(vid1).Out(\"knows\").Values(\"age\").Fold()))", + "groovy": "g.V().values(\"age\").is(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "java": "g.V().values(\"age\").is(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "javascript": "g.V().values(\"age\").is(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "python": "g.V().values('age').is_(P.within(__.V(vid1).out('knows').values('age').fold()))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXconstantX99999XX", + "traversals": [ + { + "original": "g.V().values(\"age\").is(__.constant(99999))", + "language": "g.V().values(\"age\").is(__.constant(99999))", + "canonical": "g.V().values(\"age\").is(__.constant(99999))", + "anonymized": "g.V().values(string0).is(__.constant(number0))", + "dotnet": "g.V().Values(\"age\").Is(__.Constant(99999))", + "go": "g.V().Values(\"age\").Is(gremlingo.T__.Constant(99999))", + "groovy": "g.V().values(\"age\").is(__.constant(99999))", + "java": "g.V().values(\"age\").is(__.constant(99999))", + "javascript": "g.V().values(\"age\").is(__.constant(99999))", + "python": "g.V().values('age').is_(__.constant(99999))" + } + ] + }, + { + "scenario": "g_V_hasLabelXpersonX_valuesXageX_chooseXgtXconstantX29XX_olderX", + "traversals": [ + { + "original": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gt(__.constant(29))),__.constant(\"older than marko\"),__.constant(\"not older\"))", + "language": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gt(__.constant(29))), __.constant(\"older than marko\"), __.constant(\"not older\"))", + "canonical": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gt(__.constant(29))), __.constant(\"older than marko\"), __.constant(\"not older\"))", + "anonymized": "g.V().hasLabel(string0).values(string1).choose(__.is(P.gt(__.constant(number0))), __.constant(string2), __.constant(string3))", + "dotnet": "g.V().HasLabel(\"person\").Values(\"age\").Choose(__.Is(P.Gt(__.Constant(29))), __.Constant(\"older than marko\"), __.Constant(\"not older\"))", + "go": "g.V().HasLabel(\"person\").Values(\"age\").Choose(gremlingo.T__.Is(gremlingo.P.Gt(gremlingo.T__.Constant(29))), gremlingo.T__.Constant(\"older than marko\"), gremlingo.T__.Constant(\"not older\"))", + "groovy": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gt(__.constant(29))), __.constant(\"older than marko\"), __.constant(\"not older\"))", + "java": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gt(__.constant(29))), __.constant(\"older than marko\"), __.constant(\"not older\"))", + "javascript": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gt(__.constant(29))), __.constant(\"older than marko\"), __.constant(\"not older\"))", + "python": "g.V().has_label('person').values('age').choose(__.is_(P.gt(__.constant(29))), __.constant('older than marko'), __.constant('not older'))" + } + ] + }, + { + "scenario": "g_V_hasLabelXpersonX_valuesXageX_chooseXgteXmeanAgeX_aboveX", + "traversals": [ + { + "original": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gte(__.V().hasLabel(\"person\").values(\"age\").mean())),__.constant(\"above average\"),__.constant(\"below average\"))", + "language": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gte(__.V().hasLabel(\"person\").values(\"age\").mean())), __.constant(\"above average\"), __.constant(\"below average\"))", + "canonical": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gte(__.V().hasLabel(\"person\").values(\"age\").mean())), __.constant(\"above average\"), __.constant(\"below average\"))", + "anonymized": "g.V().hasLabel(string0).values(string1).choose(__.is(P.gte(__.V().hasLabel(string0).values(string1).mean())), __.constant(string2), __.constant(string3))", + "dotnet": "g.V().HasLabel(\"person\").Values(\"age\").Choose(__.Is(P.Gte(__.V().HasLabel(\"person\").Values(\"age\").Mean())), __.Constant(\"above average\"), __.Constant(\"below average\"))", + "go": "g.V().HasLabel(\"person\").Values(\"age\").Choose(gremlingo.T__.Is(gremlingo.P.Gte(gremlingo.T__.V().HasLabel(\"person\").Values(\"age\").Mean())), gremlingo.T__.Constant(\"above average\"), gremlingo.T__.Constant(\"below average\"))", + "groovy": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gte(__.V().hasLabel(\"person\").values(\"age\").mean())), __.constant(\"above average\"), __.constant(\"below average\"))", + "java": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gte(__.V().hasLabel(\"person\").values(\"age\").mean())), __.constant(\"above average\"), __.constant(\"below average\"))", + "javascript": "g.V().hasLabel(\"person\").values(\"age\").choose(__.is(P.gte(__.V().hasLabel(\"person\").values(\"age\").mean())), __.constant(\"above average\"), __.constant(\"below average\"))", + "python": "g.V().has_label('person').values('age').choose(__.is_(P.gte(__.V().has_label('person').values('age').mean())), __.constant('above average'), __.constant('below average'))" + } + ] + }, + { + "scenario": "g_VXvid1X_outXknowsX_valuesXageX_fold_allXgteXconstantX27XXX", + "traversals": [ + { + "original": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gte(__.constant(27)))", + "language": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gte(__.constant(27)))", + "canonical": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gte(__.constant(27)))", + "anonymized": "g.V(vid1).out(string0).values(string1).fold().all(P.gte(__.constant(number0)))", + "dotnet": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().All(P.Gte(__.Constant(27)))", + "go": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().All(gremlingo.P.Gte(gremlingo.T__.Constant(27)))", + "groovy": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gte(__.constant(27)))", + "java": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gte(__.constant(27)))", + "javascript": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gte(__.constant(27)))", + "python": "g.V(vid1).out('knows').values('age').fold().all_(P.gte(__.constant(27)))" + } + ] + }, + { + "scenario": "g_VXvid1X_outXknowsX_valuesXageX_fold_allXgtXconstantX27XXX", + "traversals": [ + { + "original": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gt(__.constant(27)))", + "language": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gt(__.constant(27)))", + "canonical": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gt(__.constant(27)))", + "anonymized": "g.V(vid1).out(string0).values(string1).fold().all(P.gt(__.constant(number0)))", + "dotnet": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().All(P.Gt(__.Constant(27)))", + "go": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().All(gremlingo.P.Gt(gremlingo.T__.Constant(27)))", + "groovy": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gt(__.constant(27)))", + "java": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gt(__.constant(27)))", + "javascript": "g.V(vid1).out(\"knows\").values(\"age\").fold().all(P.gt(__.constant(27)))", + "python": "g.V(vid1).out('knows').values('age').fold().all_(P.gt(__.constant(27)))" + } + ] + }, + { + "scenario": "g_VXvid1X_outXknowsX_valuesXageX_fold_anyXeqXconstantX32XXX", + "traversals": [ + { + "original": "g.V(vid1).out(\"knows\").values(\"age\").fold().any(P.eq(__.constant(32)))", + "language": "g.V(vid1).out(\"knows\").values(\"age\").fold().any(P.eq(__.constant(32)))", + "canonical": "g.V(vid1).out(\"knows\").values(\"age\").fold().any(P.eq(__.constant(32)))", + "anonymized": "g.V(vid1).out(string0).values(string1).fold().any(P.eq(__.constant(number0)))", + "dotnet": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().Any(P.Eq(__.Constant(32)))", + "go": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().Any(gremlingo.P.Eq(gremlingo.T__.Constant(32)))", + "groovy": "g.V(vid1).out(\"knows\").values(\"age\").fold().any(P.eq(__.constant(32)))", + "java": "g.V(vid1).out(\"knows\").values(\"age\").fold().any(P.eq(__.constant(32)))", + "javascript": "g.V(vid1).out(\"knows\").values(\"age\").fold().any(P.eq(__.constant(32)))", + "python": "g.V(vid1).out('knows').values('age').fold().any_(P.eq(__.constant(32)))" + } + ] + }, + { + "scenario": "g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX35XXX", + "traversals": [ + { + "original": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(35)))", + "language": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(35)))", + "canonical": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(35)))", + "anonymized": "g.V(vid1).out(string0).values(string1).fold().none(P.eq(__.constant(number0)))", + "dotnet": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().None(P.Eq(__.Constant(35)))", + "go": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().None(gremlingo.P.Eq(gremlingo.T__.Constant(35)))", + "groovy": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(35)))", + "java": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(35)))", + "javascript": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(35)))", + "python": "g.V(vid1).out('knows').values('age').fold().none(P.eq(__.constant(35)))" + } + ] + }, + { + "scenario": "g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX32XXX", + "traversals": [ + { + "original": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(32)))", + "language": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(32)))", + "canonical": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(32)))", + "anonymized": "g.V(vid1).out(string0).values(string1).fold().none(P.eq(__.constant(number0)))", + "dotnet": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().None(P.Eq(__.Constant(32)))", + "go": "g.V(vid1).Out(\"knows\").Values(\"age\").Fold().None(gremlingo.P.Eq(gremlingo.T__.Constant(32)))", + "groovy": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(32)))", + "java": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(32)))", + "javascript": "g.V(vid1).out(\"knows\").values(\"age\").fold().none(P.eq(__.constant(32)))", + "python": "g.V(vid1).out('knows').values('age').fold().none(P.eq(__.constant(32)))" + } + ] + }, + { + "scenario": "g_injectXnullX_isXeqXV9999_valuesXnameXXX", + "traversals": [ + { + "original": "g.inject(null).is(P.eq(__.V(9999).values(\"name\")))", + "language": "g.inject(null).is(P.eq(__.V(9999).values(\"name\")))", + "canonical": "g.inject(null).is(P.eq(__.V(9999).values(\"name\")))", + "anonymized": "g.inject(object0).is(P.eq(__.V(number0).values(string0)))", + "dotnet": "g.Inject(null).Is(P.Eq(__.V(9999).Values(\"name\")))", + "go": "g.Inject(nil).Is(gremlingo.P.Eq(gremlingo.T__.V(9999).Values(\"name\")))", + "groovy": "g.inject(null).is(P.eq(__.V(9999).values(\"name\")))", + "java": "g.inject(null).is(P.eq(__.V(9999).values(\"name\")))", + "javascript": "g.inject(null).is(P.eq(__.V(9999).values(\"name\")))", + "python": "g.inject(None).is_(P.eq(__.V(9999).values('name')))" + } + ] + }, + { + "scenario": "g_injectXmarkoX_isXV9999_valuesXnameXX", + "traversals": [ + { + "original": "g.inject(\"marko\").is(__.V(9999).values(\"name\"))", + "language": "g.inject(\"marko\").is(__.V(9999).values(\"name\"))", + "canonical": "g.inject(\"marko\").is(__.V(9999).values(\"name\"))", + "anonymized": "g.inject(string0).is(__.V(number0).values(string1))", + "dotnet": "g.Inject(\"marko\").Is(__.V(9999).Values(\"name\"))", + "go": "g.Inject(\"marko\").Is(gremlingo.T__.V(9999).Values(\"name\"))", + "groovy": "g.inject(\"marko\").is(__.V(9999).values(\"name\"))", + "java": "g.inject(\"marko\").is(__.V(9999).values(\"name\"))", + "javascript": "g.inject(\"marko\").is(__.V(9999).values(\"name\"))", + "python": "g.inject('marko').is_(__.V(9999).values('name'))" + } + ] + }, + { + "scenario": "g_injectXmarkoX_chooseXeqXV9999_valuesXnameXX_matched_unmatchedX", + "traversals": [ + { + "original": "g.inject(\"marko\").choose(__.is(P.eq(__.V(9999).values(\"name\"))), __.constant(\"matched\"), __.constant(\"unmatched\"))", + "language": "g.inject(\"marko\").choose(__.is(P.eq(__.V(9999).values(\"name\"))), __.constant(\"matched\"), __.constant(\"unmatched\"))", + "canonical": "g.inject(\"marko\").choose(__.is(P.eq(__.V(9999).values(\"name\"))), __.constant(\"matched\"), __.constant(\"unmatched\"))", + "anonymized": "g.inject(string0).choose(__.is(P.eq(__.V(number0).values(string1))), __.constant(string2), __.constant(string3))", + "dotnet": "g.Inject(\"marko\").Choose(__.Is(P.Eq(__.V(9999).Values(\"name\"))), __.Constant(\"matched\"), __.Constant(\"unmatched\"))", + "go": "g.Inject(\"marko\").Choose(gremlingo.T__.Is(gremlingo.P.Eq(gremlingo.T__.V(9999).Values(\"name\"))), gremlingo.T__.Constant(\"matched\"), gremlingo.T__.Constant(\"unmatched\"))", + "groovy": "g.inject(\"marko\").choose(__.is(P.eq(__.V(9999).values(\"name\"))), __.constant(\"matched\"), __.constant(\"unmatched\"))", + "java": "g.inject(\"marko\").choose(__.is(P.eq(__.V(9999).values(\"name\"))), __.constant(\"matched\"), __.constant(\"unmatched\"))", + "javascript": "g.inject(\"marko\").choose(__.is(P.eq(__.V(9999).values(\"name\"))), __.constant(\"matched\"), __.constant(\"unmatched\"))", + "python": "g.inject('marko').choose(__.is_(P.eq(__.V(9999).values('name'))), __.constant('matched'), __.constant('unmatched'))" + } + ] + }, + { + "scenario": "g_injectXlistX_noneXeqXV9999_valuesXnameXXX", + "traversals": [ + { + "original": "g.inject([\"marko\",\"josh\"]).none(P.eq(__.V(9999).values(\"name\")))", + "language": "g.inject([\"marko\", \"josh\"]).none(P.eq(__.V(9999).values(\"name\")))", + "canonical": "g.inject([\"marko\", \"josh\"]).none(P.eq(__.V(9999).values(\"name\")))", + "anonymized": "g.inject(list0).none(P.eq(__.V(number0).values(string0)))", + "dotnet": "g.Inject(new List { \"marko\", \"josh\" }).None(P.Eq(__.V(9999).Values(\"name\")))", + "go": "g.Inject([]interface{}{\"marko\", \"josh\"}).None(gremlingo.P.Eq(gremlingo.T__.V(9999).Values(\"name\")))", + "groovy": "g.inject([\"marko\", \"josh\"]).none(P.eq(__.V(9999).values(\"name\")))", + "java": "g.inject(new ArrayList() {{ add(\"marko\"); add(\"josh\"); }}).none(P.eq(__.V(9999).values(\"name\")))", + "javascript": "g.inject([\"marko\", \"josh\"]).none(P.eq(__.V(9999).values(\"name\")))", + "python": "g.inject(['marko', 'josh']).none(P.eq(__.V(9999).values('name')))" + } + ] + }, + { + "scenario": "g_V_hasXname_eqXV9999_valuesXnameXXX", + "traversals": [ + { + "original": "g.V().has(\"name\", P.eq(__.V(9999).values(\"name\")))", + "language": "g.V().has(\"name\", P.eq(__.V(9999).values(\"name\")))", + "canonical": "g.V().has(\"name\", P.eq(__.V(9999).values(\"name\")))", + "anonymized": "g.V().has(string0, P.eq(__.V(number0).values(string0)))", + "dotnet": "g.V().Has(\"name\", P.Eq(__.V(9999).Values(\"name\")))", + "go": "g.V().Has(\"name\", gremlingo.P.Eq(gremlingo.T__.V(9999).Values(\"name\")))", + "groovy": "g.V().has(\"name\", P.eq(__.V(9999).values(\"name\")))", + "java": "g.V().has(\"name\", P.eq(__.V(9999).values(\"name\")))", + "javascript": "g.V().has(\"name\", P.eq(__.V(9999).values(\"name\")))", + "python": "g.V().has('name', P.eq(__.V(9999).values('name')))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXwithoutXconstantX29X_constantX32XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").is(P.without(__.constant(29), __.constant(32)))", + "language": "g.V().values(\"age\").is(P.without(__.constant(29), __.constant(32)))", + "canonical": "g.V().values(\"age\").is(P.without(__.constant(29), __.constant(32)))", + "anonymized": "g.V().values(string0).is(P.without(__.constant(number0), __.constant(number1)))", + "dotnet": "g.V().Values(\"age\").Is(P.Without(__.Constant(29), __.Constant(32)))", + "go": "g.V().Values(\"age\").Is(gremlingo.P.Without(gremlingo.T__.Constant(29), gremlingo.T__.Constant(32)))", + "groovy": "g.V().values(\"age\").is(P.without(__.constant(29), __.constant(32)))", + "java": "g.V().values(\"age\").is(P.without(__.constant(29), __.constant(32)))", + "javascript": "g.V().values(\"age\").is(P.without(__.constant(29), __.constant(32)))", + "python": "g.V().values('age').is_(P.without(__.constant(29), __.constant(32)))" + } + ] + }, + { + "scenario": "g_VXvid1X_asXaX_V_valuesXageX_isXgtXselectXaX_valuesXageXXX", + "traversals": [ + { + "original": "g.V(vid1).as(\"a\").V().values(\"age\").is(P.gt(__.select(\"a\").values(\"age\")))", + "language": "g.V(vid1).as(\"a\").V().values(\"age\").is(P.gt(__.select(\"a\").values(\"age\")))", + "canonical": "g.V(vid1).as(\"a\").V().values(\"age\").is(P.gt(__.select(\"a\").values(\"age\")))", + "anonymized": "g.V(vid1).as(string0).V().values(string1).is(P.gt(__.select(string0).values(string1)))", + "dotnet": "g.V(vid1).As(\"a\").V().Values(\"age\").Is(P.Gt(__.Select(\"a\").Values(\"age\")))", + "go": "g.V(vid1).As(\"a\").V().Values(\"age\").Is(gremlingo.P.Gt(gremlingo.T__.Select(\"a\").Values(\"age\")))", + "groovy": "g.V(vid1).as(\"a\").V().values(\"age\").is(P.gt(__.select(\"a\").values(\"age\")))", + "java": "g.V(vid1).as(\"a\").V().values(\"age\").is(P.gt(__.select(\"a\").values(\"age\")))", + "javascript": "g.V(vid1).as(\"a\").V().values(\"age\").is(P.gt(__.select(\"a\").values(\"age\")))", + "python": "g.V(vid1).as_('a').V().values('age').is_(P.gt(__.select('a').values('age')))" + } + ] + }, + { + "scenario": "g_withSackX30X_V_valuesXageX_isXgtXsackXX", + "traversals": [ + { + "original": "g.withSack(30).V().values(\"age\").is(P.gt(__.sack()))", + "language": "g.withSack(30).V().values(\"age\").is(P.gt(__.sack()))", + "canonical": "g.withSack(30).V().values(\"age\").is(P.gt(__.sack()))", + "anonymized": "g.withSack(number0).V().values(string0).is(P.gt(__.sack()))", + "dotnet": "g.WithSack(30).V().Values(\"age\").Is(P.Gt(__.Sack()))", + "go": "g.WithSack(30).V().Values(\"age\").Is(gremlingo.P.Gt(gremlingo.T__.Sack()))", + "groovy": "g.withSack(30).V().values(\"age\").is(P.gt(__.sack()))", + "java": "g.withSack(30).V().values(\"age\").is(P.gt(__.sack()))", + "javascript": "g.withSack(30).V().values(\"age\").is(P.gt(__.sack()))", + "python": "g.with_sack(30).V().values('age').is_(P.gt(__.sack()))" + } + ] + }, { "scenario": "g_V_valuesXageX_noneXgtX32XX", "traversals": [ @@ -12373,6 +13274,176 @@ } ] }, + { + "scenario": "g_V_valuesXageX_whereXgtXconstantX29XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.gt(__.constant(29)))", + "language": "g.V().values(\"age\").where(P.gt(__.constant(29)))", + "canonical": "g.V().values(\"age\").where(P.gt(__.constant(29)))", + "anonymized": "g.V().values(string0).where(P.gt(__.constant(number0)))", + "dotnet": "g.V().Values(\"age\").Where(P.Gt(__.Constant(29)))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Gt(gremlingo.T__.Constant(29)))", + "groovy": "g.V().values(\"age\").where(P.gt(__.constant(29)))", + "java": "g.V().values(\"age\").where(P.gt(__.constant(29)))", + "javascript": "g.V().values(\"age\").where(P.gt(__.constant(29)))", + "python": "g.V().values('age').where(P.gt(__.constant(29)))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXltXconstantX32XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.lt(__.constant(32)))", + "language": "g.V().values(\"age\").where(P.lt(__.constant(32)))", + "canonical": "g.V().values(\"age\").where(P.lt(__.constant(32)))", + "anonymized": "g.V().values(string0).where(P.lt(__.constant(number0)))", + "dotnet": "g.V().Values(\"age\").Where(P.Lt(__.Constant(32)))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Lt(gremlingo.T__.Constant(32)))", + "groovy": "g.V().values(\"age\").where(P.lt(__.constant(32)))", + "java": "g.V().values(\"age\").where(P.lt(__.constant(32)))", + "javascript": "g.V().values(\"age\").where(P.lt(__.constant(32)))", + "python": "g.V().values('age').where(P.lt(__.constant(32)))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXeqXconstantX29XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.eq(__.constant(29)))", + "language": "g.V().values(\"age\").where(P.eq(__.constant(29)))", + "canonical": "g.V().values(\"age\").where(P.eq(__.constant(29)))", + "anonymized": "g.V().values(string0).where(P.eq(__.constant(number0)))", + "dotnet": "g.V().Values(\"age\").Where(P.Eq(__.Constant(29)))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Eq(gremlingo.T__.Constant(29)))", + "groovy": "g.V().values(\"age\").where(P.eq(__.constant(29)))", + "java": "g.V().values(\"age\").where(P.eq(__.constant(29)))", + "javascript": "g.V().values(\"age\").where(P.eq(__.constant(29)))", + "python": "g.V().values('age').where(P.eq(__.constant(29)))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXwithinXVXvid1X_outXknowsX_valuesXageXXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "language": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "canonical": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "anonymized": "g.V().values(string0).where(P.within(__.V(vid1).out(string1).values(string0).fold()))", + "dotnet": "g.V().Values(\"age\").Where(P.Within(__.V(vid1).Out(\"knows\").Values(\"age\").Fold()))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Within(gremlingo.T__.V(vid1).Out(\"knows\").Values(\"age\").Fold()))", + "groovy": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "java": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "javascript": "g.V().values(\"age\").where(P.within(__.V(vid1).out(\"knows\").values(\"age\").fold()))", + "python": "g.V().values('age').where(P.within(__.V(vid1).out('knows').values('age').fold()))" + } + ] + }, + { + "scenario": "g_V_valuesXnameX_whereXneqXconstantXmarkoXXX", + "traversals": [ + { + "original": "g.V().values(\"name\").where(P.neq(__.constant(\"marko\")))", + "language": "g.V().values(\"name\").where(P.neq(__.constant(\"marko\")))", + "canonical": "g.V().values(\"name\").where(P.neq(__.constant(\"marko\")))", + "anonymized": "g.V().values(string0).where(P.neq(__.constant(string1)))", + "dotnet": "g.V().Values(\"name\").Where(P.Neq(__.Constant(\"marko\")))", + "go": "g.V().Values(\"name\").Where(gremlingo.P.Neq(gremlingo.T__.Constant(\"marko\")))", + "groovy": "g.V().values(\"name\").where(P.neq(__.constant(\"marko\")))", + "java": "g.V().values(\"name\").where(P.neq(__.constant(\"marko\")))", + "javascript": "g.V().values(\"name\").where(P.neq(__.constant(\"marko\")))", + "python": "g.V().values('name').where(P.neq(__.constant('marko')))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_whereXeqXconstantX99999XXX", + "traversals": [ + { + "original": "g.V().values(\"age\").where(P.eq(__.constant(99999)))", + "language": "g.V().values(\"age\").where(P.eq(__.constant(99999)))", + "canonical": "g.V().values(\"age\").where(P.eq(__.constant(99999)))", + "anonymized": "g.V().values(string0).where(P.eq(__.constant(number0)))", + "dotnet": "g.V().Values(\"age\").Where(P.Eq(__.Constant(99999)))", + "go": "g.V().Values(\"age\").Where(gremlingo.P.Eq(gremlingo.T__.Constant(99999)))", + "groovy": "g.V().values(\"age\").where(P.eq(__.constant(99999)))", + "java": "g.V().values(\"age\").where(P.eq(__.constant(99999)))", + "javascript": "g.V().values(\"age\").where(P.eq(__.constant(99999)))", + "python": "g.V().values('age').where(P.eq(__.constant(99999)))" + } + ] + }, + { + "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(\"age\"))).By(\"age\").Values(\"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_VX1X_asXaX_V_valuesXageX_whereXgteXconstantX0XX_andXneqXaXXX_byX_byXageX", + "traversals": [ + { + "original": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.gte(__.constant(0)).and(P.neq(\"a\"))).by().by(\"age\")", + "language": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.gte(__.constant(0)).and(P.neq(\"a\"))).by().by(\"age\")", + "canonical": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.gte(__.constant(0)).and(P.neq(\"a\"))).by().by(\"age\")", + "anonymized": "g.V(vid1).as(string0).V().hasLabel(string1).values(string2).where(P.gte(__.constant(number0)).and(P.neq(string0))).by().by(string2)", + "dotnet": "g.V(vid1).As(\"a\").V().HasLabel(\"person\").Values(\"age\").Where(P.Gte(__.Constant(0)).And(P.Neq(\"a\"))).By().By(\"age\")", + "go": "g.V(vid1).As(\"a\").V().HasLabel(\"person\").Values(\"age\").Where(gremlingo.P.Gte(gremlingo.T__.Constant(0)).And(gremlingo.P.Neq(\"a\"))).By().By(\"age\")", + "groovy": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.gte(__.constant(0)).and(P.neq(\"a\"))).by().by(\"age\")", + "java": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.gte(__.constant(0)).and(P.neq(\"a\"))).by().by(\"age\")", + "javascript": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.gte(__.constant(0)).and(P.neq(\"a\"))).by().by(\"age\")", + "python": "g.V(vid1).as_('a').V().has_label('person').values('age').where(P.gte(__.constant(0)).and_(P.neq('a'))).by().by('age')" + } + ] + }, + { + "scenario": "g_VX1X_asXaX_V_valuesXageX_whereXneqXaX_andXgtXVXvid1X_valuesXageXXXX_byX_byXageX", + "traversals": [ + { + "original": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.neq(\"a\").and(P.gt(__.V(vid1).values(\"age\")))).by().by(\"age\")", + "language": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.neq(\"a\").and(P.gt(__.V(vid1).values(\"age\")))).by().by(\"age\")", + "canonical": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.neq(\"a\").and(P.gt(__.V(vid1).values(\"age\")))).by().by(\"age\")", + "anonymized": "g.V(vid1).as(string0).V().hasLabel(string1).values(string2).where(P.neq(string0).and(P.gt(__.V(vid1).values(string2)))).by().by(string2)", + "dotnet": "g.V(vid1).As(\"a\").V().HasLabel(\"person\").Values(\"age\").Where(P.Neq(\"a\").And(P.Gt(__.V(vid1).Values(\"age\")))).By().By(\"age\")", + "go": "g.V(vid1).As(\"a\").V().HasLabel(\"person\").Values(\"age\").Where(gremlingo.P.Neq(\"a\").And(gremlingo.P.Gt(gremlingo.T__.V(vid1).Values(\"age\")))).By().By(\"age\")", + "groovy": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.neq(\"a\").and(P.gt(__.V(vid1).values(\"age\")))).by().by(\"age\")", + "java": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.neq(\"a\").and(P.gt(__.V(vid1).values(\"age\")))).by().by(\"age\")", + "javascript": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.neq(\"a\").and(P.gt(__.V(vid1).values(\"age\")))).by().by(\"age\")", + "python": "g.V(vid1).as_('a').V().has_label('person').values('age').where(P.neq('a').and_(P.gt(__.V(vid1).values('age')))).by().by('age')" + } + ] + }, + { + "scenario": "g_VX1X_asXaX_V_valuesXageX_whereXeqXVXvid1X_valuesXageXX_orXeqXaXXX_byX_byXageX", + "traversals": [ + { + "original": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.eq(__.V(vid1).values(\"age\")).or(P.eq(\"a\"))).by().by(\"age\")", + "language": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.eq(__.V(vid1).values(\"age\")).or(P.eq(\"a\"))).by().by(\"age\")", + "canonical": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.eq(__.V(vid1).values(\"age\")).or(P.eq(\"a\"))).by().by(\"age\")", + "anonymized": "g.V(vid1).as(string0).V().hasLabel(string1).values(string2).where(P.eq(__.V(vid1).values(string2)).or(P.eq(string0))).by().by(string2)", + "dotnet": "g.V(vid1).As(\"a\").V().HasLabel(\"person\").Values(\"age\").Where(P.Eq(__.V(vid1).Values(\"age\")).Or(P.Eq(\"a\"))).By().By(\"age\")", + "go": "g.V(vid1).As(\"a\").V().HasLabel(\"person\").Values(\"age\").Where(gremlingo.P.Eq(gremlingo.T__.V(vid1).Values(\"age\")).Or(gremlingo.P.Eq(\"a\"))).By().By(\"age\")", + "groovy": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.eq(__.V(vid1).values(\"age\")).or(P.eq(\"a\"))).by().by(\"age\")", + "java": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.eq(__.V(vid1).values(\"age\")).or(P.eq(\"a\"))).by().by(\"age\")", + "javascript": "g.V(vid1).as(\"a\").V().hasLabel(\"person\").values(\"age\").where(P.eq(__.V(vid1).values(\"age\")).or(P.eq(\"a\"))).by().by(\"age\")", + "python": "g.V(vid1).as_('a').V().has_label('person').values('age').where(P.eq(__.V(vid1).values('age')).or_(P.eq('a'))).by().by('age')" + } + ] + }, { "scenario": "g_withStrategiesXAdjacentToIncidentStrategyX_V", "traversals": [ @@ -14934,6 +16005,295 @@ } ] }, + { + "scenario": "g_V_hasXname_addVXxX_valuesXnameXX_rejected", + "traversals": [ + { + "original": "g.V().has(\"name\", __.addV(\"x\").values(\"name\"))", + "language": "g.V().has(\"name\", __.addV(\"x\").values(\"name\"))", + "canonical": "g.V().has(\"name\", __.addV(\"x\").values(\"name\"))", + "anonymized": "g.V().has(string0, __.addV(string1).values(string0))", + "dotnet": "g.V().Has(\"name\", __.AddV((string) \"x\").Values(\"name\"))", + "go": "g.V().Has(\"name\", gremlingo.T__.AddV(\"x\").Values(\"name\"))", + "groovy": "g.V().has(\"name\", __.addV(\"x\").values(\"name\"))", + "java": "g.V().has(\"name\", __.addV(\"x\").values(\"name\"))", + "javascript": "g.V().has(\"name\", __.addV(\"x\").values(\"name\"))", + "python": "g.V().has('name', __.add_v('x').values('name'))" + } + ] + }, + { + "scenario": "g_V_hasXname_V_drop_constantXxXX_rejected", + "traversals": [ + { + "original": "g.V().has(\"name\", __.V().drop().constant(\"x\"))", + "language": "g.V().has(\"name\", __.V().drop().constant(\"x\"))", + "canonical": "g.V().has(\"name\", __.V().drop().constant(\"x\"))", + "anonymized": "g.V().has(string0, __.V().drop().constant(string1))", + "dotnet": "g.V().Has(\"name\", __.V().Drop().Constant(\"x\"))", + "go": "g.V().Has(\"name\", gremlingo.T__.V().Drop().Constant(\"x\"))", + "groovy": "g.V().has(\"name\", __.V().drop().constant(\"x\"))", + "java": "g.V().has(\"name\", __.V().drop().constant(\"x\"))", + "javascript": "g.V().has(\"name\", __.V().drop().constant(\"x\"))", + "python": "g.V().has('name', __.V().drop().constant('x'))" + } + ] + }, + { + "scenario": "g_V_hasXname_V_mapXaddVXxXX_valuesXnameXX_rejected", + "traversals": [ + { + "original": "g.V().has(\"name\", __.V().map(__.addV(\"x\")).values(\"name\"))", + "language": "g.V().has(\"name\", __.V().map(__.addV(\"x\")).values(\"name\"))", + "canonical": "g.V().has(\"name\", __.V().map(__.addV(\"x\")).values(\"name\"))", + "anonymized": "g.V().has(string0, __.V().map(__.addV(string1)).values(string0))", + "dotnet": "g.V().Has(\"name\", __.V().Map(__.AddV((string) \"x\")).Values(\"name\"))", + "go": "g.V().Has(\"name\", gremlingo.T__.V().Map(gremlingo.T__.AddV(\"x\")).Values(\"name\"))", + "groovy": "g.V().has(\"name\", __.V().map(__.addV(\"x\")).values(\"name\"))", + "java": "g.V().has(\"name\", __.V().map(__.addV(\"x\")).values(\"name\"))", + "javascript": "g.V().has(\"name\", __.V().map(__.addV(\"x\")).values(\"name\"))", + "python": "g.V().has('name', __.V().map(__.add_v('x')).values('name'))" + } + ] + }, + { + "scenario": "g_V_hasXname_eqXaddVXxX_valuesXnameXXX_rejected", + "traversals": [ + { + "original": "g.V().has(\"name\", P.eq(__.addV(\"x\").values(\"name\")))", + "language": "g.V().has(\"name\", P.eq(__.addV(\"x\").values(\"name\")))", + "canonical": "g.V().has(\"name\", P.eq(__.addV(\"x\").values(\"name\")))", + "anonymized": "g.V().has(string0, P.eq(__.addV(string1).values(string0)))", + "dotnet": "g.V().Has(\"name\", P.Eq(__.AddV((string) \"x\").Values(\"name\")))", + "go": "g.V().Has(\"name\", gremlingo.P.Eq(gremlingo.T__.AddV(\"x\").Values(\"name\")))", + "groovy": "g.V().has(\"name\", P.eq(__.addV(\"x\").values(\"name\")))", + "java": "g.V().has(\"name\", P.eq(__.addV(\"x\").values(\"name\")))", + "javascript": "g.V().has(\"name\", P.eq(__.addV(\"x\").values(\"name\")))", + "python": "g.V().has('name', P.eq(__.add_v('x').values('name')))" + } + ] + }, + { + "scenario": "g_V_hasXname_withinXaddVXxX_valuesXnameXXX_rejected", + "traversals": [ + { + "original": "g.V().has(\"name\", P.within(__.addV(\"x\").values(\"name\")))", + "language": "g.V().has(\"name\", P.within(__.addV(\"x\").values(\"name\")))", + "canonical": "g.V().has(\"name\", P.within(__.addV(\"x\").values(\"name\")))", + "anonymized": "g.V().has(string0, P.within(__.addV(string1).values(string0)))", + "dotnet": "g.V().Has(\"name\", P.Within(__.AddV((string) \"x\").Values(\"name\")))", + "go": "g.V().Has(\"name\", gremlingo.P.Within(gremlingo.T__.AddV(\"x\").Values(\"name\")))", + "groovy": "g.V().has(\"name\", P.within(__.addV(\"x\").values(\"name\")))", + "java": "g.V().has(\"name\", P.within(__.addV(\"x\").values(\"name\")))", + "javascript": "g.V().has(\"name\", P.within(__.addV(\"x\").values(\"name\")))", + "python": "g.V().has('name', P.within(__.add_v('x').values('name')))" + } + ] + }, + { + "scenario": "g_V_hasXage_gtXaddVXxX_valuesXageXXX_rejected", + "traversals": [ + { + "original": "g.V().has(\"age\", P.gt(__.addV(\"x\").values(\"age\")))", + "language": "g.V().has(\"age\", P.gt(__.addV(\"x\").values(\"age\")))", + "canonical": "g.V().has(\"age\", P.gt(__.addV(\"x\").values(\"age\")))", + "anonymized": "g.V().has(string0, P.gt(__.addV(string1).values(string0)))", + "dotnet": "g.V().Has(\"age\", P.Gt(__.AddV((string) \"x\").Values(\"age\")))", + "go": "g.V().Has(\"age\", gremlingo.P.Gt(gremlingo.T__.AddV(\"x\").Values(\"age\")))", + "groovy": "g.V().has(\"age\", P.gt(__.addV(\"x\").values(\"age\")))", + "java": "g.V().has(\"age\", P.gt(__.addV(\"x\").values(\"age\")))", + "javascript": "g.V().has(\"age\", P.gt(__.addV(\"x\").values(\"age\")))", + "python": "g.V().has('age', P.gt(__.add_v('x').values('age')))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXaddVXxX_valuesXageXX_rejected", + "traversals": [ + { + "original": "g.V().values(\"age\").is(__.addV(\"x\").values(\"age\"))", + "language": "g.V().values(\"age\").is(__.addV(\"x\").values(\"age\"))", + "canonical": "g.V().values(\"age\").is(__.addV(\"x\").values(\"age\"))", + "anonymized": "g.V().values(string0).is(__.addV(string1).values(string0))", + "dotnet": "g.V().Values(\"age\").Is(__.AddV((string) \"x\").Values(\"age\"))", + "go": "g.V().Values(\"age\").Is(gremlingo.T__.AddV(\"x\").Values(\"age\"))", + "groovy": "g.V().values(\"age\").is(__.addV(\"x\").values(\"age\"))", + "java": "g.V().values(\"age\").is(__.addV(\"x\").values(\"age\"))", + "javascript": "g.V().values(\"age\").is(__.addV(\"x\").values(\"age\"))", + "python": "g.V().values('age').is_(__.add_v('x').values('age'))" + } + ] + }, + { + "scenario": "g_V_valuesXageX_isXgtXaddVXxX_valuesXageXXX_rejected", + "traversals": [ + { + "original": "g.V().values(\"age\").is(P.gt(__.addV(\"x\").values(\"age\")))", + "language": "g.V().values(\"age\").is(P.gt(__.addV(\"x\").values(\"age\")))", + "canonical": "g.V().values(\"age\").is(P.gt(__.addV(\"x\").values(\"age\")))", + "anonymized": "g.V().values(string0).is(P.gt(__.addV(string1).values(string0)))", + "dotnet": "g.V().Values(\"age\").Is(P.Gt(__.AddV((string) \"x\").Values(\"age\")))", + "go": "g.V().Values(\"age\").Is(gremlingo.P.Gt(gremlingo.T__.AddV(\"x\").Values(\"age\")))", + "groovy": "g.V().values(\"age\").is(P.gt(__.addV(\"x\").values(\"age\")))", + "java": "g.V().values(\"age\").is(P.gt(__.addV(\"x\").values(\"age\")))", + "javascript": "g.V().values(\"age\").is(P.gt(__.addV(\"x\").values(\"age\")))", + "python": "g.V().values('age').is_(P.gt(__.add_v('x').values('age')))" + } + ] + }, + { + "scenario": "g_V_VXaddVXxX_idX_rejected", + "traversals": [ + { + "original": "g.V().V(__.addV(\"x\").id())", + "language": "g.V().V(__.addV(\"x\").id())", + "canonical": "g.V().V(__.addV(\"x\").id())", + "anonymized": "g.V().V(__.addV(string0).id())", + "dotnet": "g.V().V(__.AddV((string) \"x\").Id())", + "go": "g.V().V(gremlingo.T__.AddV(\"x\").Id())", + "groovy": "g.V().V(__.addV(\"x\").id())", + "java": "g.V().V(__.addV(\"x\").id())", + "javascript": "g.V().V(__.addV(\"x\").id())", + "python": "g.V().V(__.add_v('x').id_())" + } + ] + }, + { + "scenario": "g_V_EXaddVXxX_idX_rejected", + "traversals": [ + { + "original": "g.V().E(__.addV(\"x\").id())", + "language": "g.V().E(__.addV(\"x\").id())", + "canonical": "g.V().E(__.addV(\"x\").id())", + "anonymized": "g.V().E(__.addV(string0).id())", + "dotnet": "g.V().E(__.AddV((string) \"x\").Id())", + "go": "g.V().E(gremlingo.T__.AddV(\"x\").Id())", + "groovy": "g.V().E(__.addV(\"x\").id())", + "java": "g.V().E(__.addV(\"x\").id())", + "javascript": "g.V().E(__.addV(\"x\").id())", + "python": "g.V().E(__.add_v('x').id_())" + } + ] + }, + { + "scenario": "g_VXaddVXxX_idX_rejected", + "traversals": [ + { + "original": "g.V(__.addV(\"x\").id())", + "language": "g.V(__.addV(\"x\").id())", + "canonical": "g.V(__.addV(\"x\").id())", + "anonymized": "g.V(__.addV(string0).id())", + "dotnet": "g.V(__.AddV((string) \"x\").Id())", + "go": "g.V(gremlingo.T__.AddV(\"x\").Id())", + "groovy": "g.V(__.addV(\"x\").id())", + "java": "g.V(__.addV(\"x\").id())", + "javascript": "g.V(__.addV(\"x\").id())", + "python": "g.V(__.add_v('x').id_())" + } + ] + }, + { + "scenario": "g_EXaddVXxX_idX_rejected", + "traversals": [ + { + "original": "g.E(__.addV(\"x\").id())", + "language": "g.E(__.addV(\"x\").id())", + "canonical": "g.E(__.addV(\"x\").id())", + "anonymized": "g.E(__.addV(string0).id())", + "dotnet": "g.E(__.AddV((string) \"x\").Id())", + "go": "g.E(gremlingo.T__.AddV(\"x\").Id())", + "groovy": "g.E(__.addV(\"x\").id())", + "java": "g.E(__.addV(\"x\").id())", + "javascript": "g.E(__.addV(\"x\").id())", + "python": "g.E(__.add_v('x').id_())" + } + ] + }, + { + "scenario": "g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected", + "traversals": [ + { + "original": "g.V().property(__.V().map(__.drop()).project(\"x\").by(\"name\"))", + "language": "g.V().property(__.V().map(__.drop()).project(\"x\").by(\"name\"))", + "canonical": "g.V().property(__.V().map(__.drop()).project(\"x\").by(\"name\"))", + "anonymized": "g.V().property(__.V().map(__.drop()).project(string0).by(string1))", + "dotnet": "g.V().Property((ITraversal) __.V().Map(__.Drop()).Project(\"x\").By(\"name\"))", + "go": "g.V().Property(gremlingo.T__.V().Map(gremlingo.T__.Drop()).Project(\"x\").By(\"name\"))", + "groovy": "g.V().property(__.V().map(__.drop()).project(\"x\").by(\"name\"))", + "java": "g.V().property(__.V().map(__.drop()).project(\"x\").by(\"name\"))", + "javascript": "g.V().property(__.V().map(__.drop()).project(\"x\").by(\"name\"))", + "python": "g.V().property(__.V().map(__.drop()).project('x').by('name'))" + } + ] + }, + { + "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(\"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": [ + { + "original": "g.V().has(\"name\", __.V(vid1).values(\"name\"))", + "language": "g.V().has(\"name\", __.V(vid1).values(\"name\"))", + "canonical": "g.V().has(\"name\", __.V(vid1).values(\"name\"))", + "anonymized": "g.V().has(string0, __.V(vid1).values(string0))", + "dotnet": "g.V().Has(\"name\", __.V(vid1).Values(\"name\"))", + "go": "g.V().Has(\"name\", gremlingo.T__.V(vid1).Values(\"name\"))", + "groovy": "g.V().has(\"name\", __.V(vid1).values(\"name\"))", + "java": "g.V().has(\"name\", __.V(vid1).values(\"name\"))", + "javascript": "g.V().has(\"name\", __.V(vid1).values(\"name\"))", + "python": "g.V().has('name', __.V(vid1).values('name'))" + } + ] + }, + { + "scenario": "g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification", + "traversals": [ + { + "original": "g.V().has(\"age\", P.gt(__.V(vid1).values(\"age\")))", + "language": "g.V().has(\"age\", P.gt(__.V(vid1).values(\"age\")))", + "canonical": "g.V().has(\"age\", P.gt(__.V(vid1).values(\"age\")))", + "anonymized": "g.V().has(string0, P.gt(__.V(vid1).values(string0)))", + "dotnet": "g.V().Has(\"age\", P.Gt(__.V(vid1).Values(\"age\")))", + "go": "g.V().Has(\"age\", gremlingo.P.Gt(gremlingo.T__.V(vid1).Values(\"age\")))", + "groovy": "g.V().has(\"age\", P.gt(__.V(vid1).values(\"age\")))", + "java": "g.V().has(\"age\", P.gt(__.V(vid1).values(\"age\")))", + "javascript": "g.V().has(\"age\", P.gt(__.V(vid1).values(\"age\")))", + "python": "g.V().has('age', P.gt(__.V(vid1).values('age')))" + } + ] + }, + { + "scenario": "g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification", + "traversals": [ + { + "original": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "language": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "canonical": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "anonymized": "g.V(vid1).V(__.out(string0).id()).values(string1)", + "dotnet": "g.V(vid1).V(__.Out(\"knows\").Id()).Values(\"name\")", + "go": "g.V(vid1).V(gremlingo.T__.Out(\"knows\").Id()).Values(\"name\")", + "groovy": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "java": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "javascript": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "python": "g.V(vid1).V(__.out('knows').id_()).values('name')" + } + ] + }, { "scenario": "g_withStrategiesXSubgraphStrategyXsubgraphAXX_V", "traversals": [ @@ -18984,7 +20344,7 @@ "language": "g.addV(\"person\").property(null)", "canonical": "g.addV(\"person\").property(null)", "anonymized": "g.addV(string0).property(map0)", - "dotnet": "g.AddV((string) \"person\").Property(null)", + "dotnet": "g.AddV((string) \"person\").Property((IDictionary) null)", "go": "g.AddV(\"person\").Property(nil)", "groovy": "g.addV(\"person\").property(null)", "java": "g.addV(\"person\").property(null)", @@ -19042,7 +20402,7 @@ "language": "g.addV(\"foo\").property(Cardinality.set, null)", "canonical": "g.addV(\"foo\").property(Cardinality.set, null)", "anonymized": "g.addV(string0).property(Cardinality.set, map0)", - "dotnet": "g.AddV((string) \"foo\").Property(Cardinality.Set, null)", + "dotnet": "g.AddV((string) \"foo\").Property(Cardinality.Set, (IDictionary) null)", "go": "g.AddV(\"foo\").Property(gremlingo.Cardinality.Set, nil)", "groovy": "g.addV(\"foo\").property(Cardinality.set, null)", "java": "g.addV(\"foo\").property(Cardinality.set, null)", @@ -23335,6 +24695,74 @@ } ] }, + { + "scenario": "g_VXvid1X_EXoutE_idX", + "traversals": [ + { + "original": "g.V(vid1).E(__.outE().id())", + "language": "g.V(vid1).E(__.outE().id())", + "canonical": "g.V(vid1).E(__.outE().id())", + "anonymized": "g.V(vid1).E(__.outE().id())", + "dotnet": "g.V(vid1).E(__.OutE().Id())", + "go": "g.V(vid1).E(gremlingo.T__.OutE().Id())", + "groovy": "g.V(vid1).E(__.outE().id())", + "java": "g.V(vid1).E(__.outE().id())", + "javascript": "g.V(vid1).E(__.outE().id())", + "python": "g.V(vid1).E(__.out_e().id_())" + } + ] + }, + { + "scenario": "g_VXvid1X_outEXknowsX_hasXinV_name_vadasX_id_EXidentityX", + "traversals": [ + { + "original": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\",\"vadas\")).id().E(__.identity())", + "language": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", \"vadas\")).id().E(__.identity())", + "canonical": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", \"vadas\")).id().E(__.identity())", + "anonymized": "g.V(vid1).outE(string0).filter(__.inV().has(string1, string2)).id().E(__.identity())", + "dotnet": "g.V(vid1).OutE(\"knows\").Filter(__.InV().Has(\"name\", \"vadas\")).Id().E(__.Identity())", + "go": "g.V(vid1).OutE(\"knows\").Filter(gremlingo.T__.InV().Has(\"name\", \"vadas\")).Id().E(gremlingo.T__.Identity())", + "groovy": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", \"vadas\")).id().E(__.identity())", + "java": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", \"vadas\")).id().E(__.identity())", + "javascript": "g.V(vid1).outE(\"knows\").filter(__.inV().has(\"name\", \"vadas\")).id().E(__.identity())", + "python": "g.V(vid1).out_e('knows').filter_(__.in_v().has('name', 'vadas')).id_().E(__.identity())" + } + ] + }, + { + "scenario": "g_injectX9999X_EXidentityX", + "traversals": [ + { + "original": "g.inject(9999).E(__.identity())", + "language": "g.inject(9999).E(__.identity())", + "canonical": "g.inject(9999).E(__.identity())", + "anonymized": "g.inject(number0).E(__.identity())", + "dotnet": "g.Inject(9999).E(__.Identity())", + "go": "g.Inject(9999).E(gremlingo.T__.Identity())", + "groovy": "g.inject(9999).E(__.identity())", + "java": "g.inject(9999).E(__.identity())", + "javascript": "g.inject(9999).E(__.identity())", + "python": "g.inject(9999).E(__.identity())" + } + ] + }, + { + "scenario": "g_EXVXvid1X_outE_idX", + "traversals": [ + { + "original": "g.E(__.V(vid1).outE().id())", + "language": "g.E(__.V(vid1).outE().id())", + "canonical": "g.E(__.V(vid1).outE().id())", + "anonymized": "g.E(__.V(vid1).outE().id())", + "dotnet": "g.E(__.V(vid1).OutE().Id())", + "go": "g.E(gremlingo.T__.V(vid1).OutE().Id())", + "groovy": "g.E(__.V(vid1).outE().id())", + "java": "g.E(__.V(vid1).outE().id())", + "javascript": "g.E(__.V(vid1).outE().id())", + "python": "g.E(__.V(vid1).out_e().id_())" + } + ] + }, { "scenario": "g_VX1X_properties_element", "traversals": [ @@ -38667,6 +40095,108 @@ } ] }, + { + "scenario": "g_VXvid1X_id_VXidentityX_name", + "traversals": [ + { + "original": "g.V(vid1).id().V(__.identity()).values(\"name\")", + "language": "g.V(vid1).id().V(__.identity()).values(\"name\")", + "canonical": "g.V(vid1).id().V(__.identity()).values(\"name\")", + "anonymized": "g.V(vid1).id().V(__.identity()).values(string0)", + "dotnet": "g.V(vid1).Id().V(__.Identity()).Values(\"name\")", + "go": "g.V(vid1).Id().V(gremlingo.T__.Identity()).Values(\"name\")", + "groovy": "g.V(vid1).id().V(__.identity()).values(\"name\")", + "java": "g.V(vid1).id().V(__.identity()).values(\"name\")", + "javascript": "g.V(vid1).id().V(__.identity()).values(\"name\")", + "python": "g.V(vid1).id_().V(__.identity()).values('name')" + } + ] + }, + { + "scenario": "g_VXvid1_vid2X_id_VXidentityX_name", + "traversals": [ + { + "original": "g.V(vid1, vid2).id().V(__.identity()).values(\"name\")", + "language": "g.V(vid1, vid2).id().V(__.identity()).values(\"name\")", + "canonical": "g.V(vid1, vid2).id().V(__.identity()).values(\"name\")", + "anonymized": "g.V(vid1, vid2).id().V(__.identity()).values(string0)", + "dotnet": "g.V(vid1, vid2).Id().V(__.Identity()).Values(\"name\")", + "go": "g.V(vid1, vid2).Id().V(gremlingo.T__.Identity()).Values(\"name\")", + "groovy": "g.V(vid1, vid2).id().V(__.identity()).values(\"name\")", + "java": "g.V(vid1, vid2).id().V(__.identity()).values(\"name\")", + "javascript": "g.V(vid1, vid2).id().V(__.identity()).values(\"name\")", + "python": "g.V(vid1, vid2).id_().V(__.identity()).values('name')" + } + ] + }, + { + "scenario": "g_VXvid1X_id_asXbookmarkX_V_hasXname_joshX_VXselectXbookmarkXX_name", + "traversals": [ + { + "original": "g.V(vid1).id().as(\"bookmark\").V().has(\"name\",\"josh\").V(__.select(\"bookmark\")).values(\"name\")", + "language": "g.V(vid1).id().as(\"bookmark\").V().has(\"name\", \"josh\").V(__.select(\"bookmark\")).values(\"name\")", + "canonical": "g.V(vid1).id().as(\"bookmark\").V().has(\"name\", \"josh\").V(__.select(\"bookmark\")).values(\"name\")", + "anonymized": "g.V(vid1).id().as(string0).V().has(string1, string2).V(__.select(string0)).values(string1)", + "dotnet": "g.V(vid1).Id().As(\"bookmark\").V().Has(\"name\", \"josh\").V(__.Select(\"bookmark\")).Values(\"name\")", + "go": "g.V(vid1).Id().As(\"bookmark\").V().Has(\"name\", \"josh\").V(gremlingo.T__.Select(\"bookmark\")).Values(\"name\")", + "groovy": "g.V(vid1).id().as(\"bookmark\").V().has(\"name\", \"josh\").V(__.select(\"bookmark\")).values(\"name\")", + "java": "g.V(vid1).id().as(\"bookmark\").V().has(\"name\", \"josh\").V(__.select(\"bookmark\")).values(\"name\")", + "javascript": "g.V(vid1).id().as(\"bookmark\").V().has(\"name\", \"josh\").V(__.select(\"bookmark\")).values(\"name\")", + "python": "g.V(vid1).id_().as_('bookmark').V().has('name', 'josh').V(__.select('bookmark')).values('name')" + } + ] + }, + { + "scenario": "g_VXvid1X_VXoutXknowsX_idX_name", + "traversals": [ + { + "original": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "language": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "canonical": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "anonymized": "g.V(vid1).V(__.out(string0).id()).values(string1)", + "dotnet": "g.V(vid1).V(__.Out(\"knows\").Id()).Values(\"name\")", + "go": "g.V(vid1).V(gremlingo.T__.Out(\"knows\").Id()).Values(\"name\")", + "groovy": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "java": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "javascript": "g.V(vid1).V(__.out(\"knows\").id()).values(\"name\")", + "python": "g.V(vid1).V(__.out('knows').id_()).values('name')" + } + ] + }, + { + "scenario": "g_injectX9999X_VXidentityX", + "traversals": [ + { + "original": "g.inject(9999).V(__.identity())", + "language": "g.inject(9999).V(__.identity())", + "canonical": "g.inject(9999).V(__.identity())", + "anonymized": "g.inject(number0).V(__.identity())", + "dotnet": "g.Inject(9999).V(__.Identity())", + "go": "g.Inject(9999).V(gremlingo.T__.Identity())", + "groovy": "g.inject(9999).V(__.identity())", + "java": "g.inject(9999).V(__.identity())", + "javascript": "g.inject(9999).V(__.identity())", + "python": "g.inject(9999).V(__.identity())" + } + ] + }, + { + "scenario": "g_VXVXvid1X_idX_name", + "traversals": [ + { + "original": "g.V(__.V(vid1).id()).values(\"name\")", + "language": "g.V(__.V(vid1).id()).values(\"name\")", + "canonical": "g.V(__.V(vid1).id()).values(\"name\")", + "anonymized": "g.V(__.V(vid1).id()).values(string0)", + "dotnet": "g.V(__.V(vid1).Id()).Values(\"name\")", + "go": "g.V(gremlingo.T__.V(vid1).Id()).Values(\"name\")", + "groovy": "g.V(__.V(vid1).id()).values(\"name\")", + "java": "g.V(__.V(vid1).id()).values(\"name\")", + "javascript": "g.V(__.V(vid1).id()).values(\"name\")", + "python": "g.V(__.V(vid1).id_()).values('name')" + } + ] + }, { "scenario": "InjectXnullX_eqXnullX", "traversals": [ @@ -43339,6 +44869,416 @@ } ] }, + { + "scenario": "g_VXvid2X_propertyXalias_VXvid1X_valuesXnameXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).addV(string0).property(string1, string4).property(string3, number1).addV(string5).property(string1, string6).property(string7, string8).addV(string0).property(string1, string9).property(string3, number2).addV(string0).property(string1, string10).property(string3, number3).addV(string5).property(string1, string11).property(string7, string8)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java')" + }, + { + "original": "g.V(vid2).property(\"alias\", __.V(vid1).values(\"name\"))", + "language": "g.V(vid2).property(\"alias\", __.V(vid1).values(\"name\"))", + "canonical": "g.V(vid2).property(\"alias\", __.V(vid1).values(\"name\"))", + "anonymized": "g.V(vid2).property(string0, __.V(vid1).values(string1))", + "dotnet": "g.V(vid2).Property(\"alias\", __.V(vid1).Values(\"name\"))", + "go": "g.V(vid2).Property(\"alias\", gremlingo.T__.V(vid1).Values(\"name\"))", + "groovy": "g.V(vid2).property(\"alias\", __.V(vid1).values(\"name\"))", + "java": "g.V(vid2).property(\"alias\", __.V(vid1).values(\"name\"))", + "javascript": "g.V(vid2).property(\"alias\", __.V(vid1).values(\"name\"))", + "python": "g.V(vid2).property('alias', __.V(vid1).values('name'))" + }, + { + "original": "g.V().has(\"alias\", \"marko\")", + "language": "g.V().has(\"alias\", \"marko\")", + "canonical": "g.V().has(\"alias\", \"marko\")", + "anonymized": "g.V().has(string0, string1)", + "dotnet": "g.V().Has(\"alias\", \"marko\")", + "go": "g.V().Has(\"alias\", \"marko\")", + "groovy": "g.V().has(\"alias\", \"marko\")", + "java": "g.V().has(\"alias\", \"marko\")", + "javascript": "g.V().has(\"alias\", \"marko\")", + "python": "g.V().has('alias', 'marko')" + } + ] + }, + { + "scenario": "g_VXvid1X_propertyXcreatorCount_VXvid1X_inXcreatedX_countX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).as(\"marko\").addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").as(\"lop\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).as(\"josh\").addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).as(\"peter\").addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\",\"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).as(string2).addV(string0).property(string1, string4).property(string3, number1).addV(string5).property(string1, string6).property(string7, string8).as(string6).addV(string0).property(string1, string9).property(string3, number2).as(string9).addV(string0).property(string1, string10).property(string3, number3).as(string10).addV(string5).property(string1, string11).property(string7, string8).as(string11).addE(string12).from(string2).to(__.V().has(string1, string4)).addE(string12).from(string2).to(string9).addE(string13).from(string2).to(string6).addE(string13).from(string9).to(string6).addE(string13).from(string9).to(string11).addE(string13).from(string10).to(string6)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).As(\"peter\").AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE((string) \"knows\").From(\"marko\").To(__.V().Has(\"name\", \"vadas\")).AddE((string) \"knows\").From(\"marko\").To(\"josh\").AddE((string) \"created\").From(\"marko\").To(\"lop\").AddE((string) \"created\").From(\"josh\").To(\"lop\").AddE((string) \"created\").From(\"josh\").To(\"ripple\").AddE((string) \"created\").From(\"peter\").To(\"lop\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).As(\"peter\").AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE(\"knows\").From(\"marko\").To(gremlingo.T__.V().Has(\"name\", \"vadas\")).AddE(\"knows\").From(\"marko\").To(\"josh\").AddE(\"created\").From(\"marko\").To(\"lop\").AddE(\"created\").From(\"josh\").To(\"lop\").AddE(\"created\").From(\"josh\").To(\"ripple\").AddE(\"created\").From(\"peter\").To(\"lop\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from_(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from_(\"marko\").to(\"josh\").addE(\"created\").from_(\"marko\").to(\"lop\").addE(\"created\").from_(\"josh\").to(\"lop\").addE(\"created\").from_(\"josh\").to(\"ripple\").addE(\"created\").from_(\"peter\").to(\"lop\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).as_('peter').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('knows').from_('marko').to(__.V().has('name', 'vadas')).add_e('knows').from_('marko').to('josh').add_e('created').from_('marko').to('lop').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple').add_e('created').from_('peter').to('lop')" + }, + { + "original": "g.V(vid1).property(\"creatorCount\", __.V(vid1).in(\"created\").count())", + "language": "g.V(vid1).property(\"creatorCount\", __.V(vid1).in(\"created\").count())", + "canonical": "g.V(vid1).property(\"creatorCount\", __.V(vid1).in(\"created\").count())", + "anonymized": "g.V(vid1).property(string0, __.V(vid1).in(string1).count())", + "dotnet": "g.V(vid1).Property(\"creatorCount\", __.V(vid1).In(\"created\").Count())", + "go": "g.V(vid1).Property(\"creatorCount\", gremlingo.T__.V(vid1).In(\"created\").Count())", + "groovy": "g.V(vid1).property(\"creatorCount\", __.V(vid1).in(\"created\").count())", + "java": "g.V(vid1).property(\"creatorCount\", __.V(vid1).in(\"created\").count())", + "javascript": "g.V(vid1).property(\"creatorCount\", __.V(vid1).in_(\"created\").count())", + "python": "g.V(vid1).property('creatorCount', __.V(vid1).in_('created').count())" + }, + { + "original": "g.V().has(\"creatorCount\", 3L)", + "language": "g.V().has(\"creatorCount\", 3l)", + "canonical": "g.V().has(\"creatorCount\", 3l)", + "anonymized": "g.V().has(string0, long0)", + "dotnet": "g.V().Has(\"creatorCount\", 3l)", + "go": "g.V().Has(\"creatorCount\", int64(3))", + "groovy": "g.V().has(\"creatorCount\", 3l)", + "java": "g.V().has(\"creatorCount\", 3l)", + "javascript": "g.V().has(\"creatorCount\", 3)", + "python": "g.V().has('creatorCount', long(3))" + } + ] + }, + { + "scenario": "g_VXvid1X_propertyXknownCount_outXknowsX_countX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).as(\"marko\").addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).as(\"vadas\").addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).as(\"josh\").addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).as(string2).addV(string0).property(string1, string4).property(string3, number1).as(string4).addV(string5).property(string1, string6).property(string7, string8).addV(string0).property(string1, string9).property(string3, number2).as(string9).addV(string0).property(string1, string10).property(string3, number3).addV(string5).property(string1, string11).property(string7, string8).addE(string12).from(string2).to(string4).addE(string12).from(string2).to(string9)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").AddE((string) \"knows\").From(\"marko\").To(\"vadas\").AddE((string) \"knows\").From(\"marko\").To(\"josh\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").AddE(\"knows\").From(\"marko\").To(\"vadas\").AddE(\"knows\").From(\"marko\").To(\"josh\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from_(\"marko\").to(\"vadas\").addE(\"knows\").from_(\"marko\").to(\"josh\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh')" + }, + { + "original": "g.V(vid1).property(\"knownCount\", __.out(\"knows\").count())", + "language": "g.V(vid1).property(\"knownCount\", __.out(\"knows\").count())", + "canonical": "g.V(vid1).property(\"knownCount\", __.out(\"knows\").count())", + "anonymized": "g.V(vid1).property(string0, __.out(string1).count())", + "dotnet": "g.V(vid1).Property(\"knownCount\", __.Out(\"knows\").Count())", + "go": "g.V(vid1).Property(\"knownCount\", gremlingo.T__.Out(\"knows\").Count())", + "groovy": "g.V(vid1).property(\"knownCount\", __.out(\"knows\").count())", + "java": "g.V(vid1).property(\"knownCount\", __.out(\"knows\").count())", + "javascript": "g.V(vid1).property(\"knownCount\", __.out(\"knows\").count())", + "python": "g.V(vid1).property('knownCount', __.out('knows').count())" + }, + { + "original": "g.V().has(\"knownCount\", 2L)", + "language": "g.V().has(\"knownCount\", 2l)", + "canonical": "g.V().has(\"knownCount\", 2l)", + "anonymized": "g.V().has(string0, long0)", + "dotnet": "g.V().Has(\"knownCount\", 2l)", + "go": "g.V().Has(\"knownCount\", int64(2))", + "groovy": "g.V().has(\"knownCount\", 2l)", + "java": "g.V().has(\"knownCount\", 2l)", + "javascript": "g.V().has(\"knownCount\", 2)", + "python": "g.V().has('knownCount', long(2))" + } + ] + }, + { + "scenario": "g_VXvid1X_propertyXcreator_inXcreatedX_valuesXnameXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).as(\"marko\").addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").as(\"lop\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).as(\"josh\").addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).as(\"peter\").addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\",\"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).as(string2).addV(string0).property(string1, string4).property(string3, number1).addV(string5).property(string1, string6).property(string7, string8).as(string6).addV(string0).property(string1, string9).property(string3, number2).as(string9).addV(string0).property(string1, string10).property(string3, number3).as(string10).addV(string5).property(string1, string11).property(string7, string8).as(string11).addE(string12).from(string2).to(__.V().has(string1, string4)).addE(string12).from(string2).to(string9).addE(string13).from(string2).to(string6).addE(string13).from(string9).to(string6).addE(string13).from(string9).to(string11).addE(string13).from(string10).to(string6)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).As(\"peter\").AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE((string) \"knows\").From(\"marko\").To(__.V().Has(\"name\", \"vadas\")).AddE((string) \"knows\").From(\"marko\").To(\"josh\").AddE((string) \"created\").From(\"marko\").To(\"lop\").AddE((string) \"created\").From(\"josh\").To(\"lop\").AddE((string) \"created\").From(\"josh\").To(\"ripple\").AddE((string) \"created\").From(\"peter\").To(\"lop\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).As(\"peter\").AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE(\"knows\").From(\"marko\").To(gremlingo.T__.V().Has(\"name\", \"vadas\")).AddE(\"knows\").From(\"marko\").To(\"josh\").AddE(\"created\").From(\"marko\").To(\"lop\").AddE(\"created\").From(\"josh\").To(\"lop\").AddE(\"created\").From(\"josh\").To(\"ripple\").AddE(\"created\").From(\"peter\").To(\"lop\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from_(\"marko\").to(__.V().has(\"name\", \"vadas\")).addE(\"knows\").from_(\"marko\").to(\"josh\").addE(\"created\").from_(\"marko\").to(\"lop\").addE(\"created\").from_(\"josh\").to(\"lop\").addE(\"created\").from_(\"josh\").to(\"ripple\").addE(\"created\").from_(\"peter\").to(\"lop\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).as_('peter').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('knows').from_('marko').to(__.V().has('name', 'vadas')).add_e('knows').from_('marko').to('josh').add_e('created').from_('marko').to('lop').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple').add_e('created').from_('peter').to('lop')" + }, + { + "original": "g.V(vid1).property(\"creator\", __.in(\"created\").values(\"name\"))", + "language": "g.V(vid1).property(\"creator\", __.in(\"created\").values(\"name\"))", + "canonical": "g.V(vid1).property(\"creator\", __.in(\"created\").values(\"name\"))", + "anonymized": "g.V(vid1).property(string0, __.in(string1).values(string2))", + "dotnet": "g.V(vid1).Property(\"creator\", __.In(\"created\").Values(\"name\"))", + "go": "g.V(vid1).Property(\"creator\", gremlingo.T__.In(\"created\").Values(\"name\"))", + "groovy": "g.V(vid1).property(\"creator\", __.in(\"created\").values(\"name\"))", + "java": "g.V(vid1).property(\"creator\", __.in(\"created\").values(\"name\"))", + "javascript": "g.V(vid1).property(\"creator\", __.in_(\"created\").values(\"name\"))", + "python": "g.V(vid1).property('creator', __.in_('created').values('name'))" + }, + { + "original": "g.V().has(\"creator\")", + "language": "g.V().has(\"creator\")", + "canonical": "g.V().has(\"creator\")", + "anonymized": "g.V().has(string0)", + "dotnet": "g.V().Has(\"creator\")", + "go": "g.V().Has(\"creator\")", + "groovy": "g.V().has(\"creator\")", + "java": "g.V().has(\"creator\")", + "javascript": "g.V().has(\"creator\")", + "python": "g.V().has('creator')" + } + ] + }, + { + "scenario": "g_VXvid2X_propertyXVXvid1X_projectXfriendCount_softwareCreatedXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).as(\"marko\").addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).as(\"vadas\").addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").as(\"lop\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).as(\"josh\").addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).as(\"peter\").addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).as(string2).addV(string0).property(string1, string4).property(string3, number1).as(string4).addV(string5).property(string1, string6).property(string7, string8).as(string6).addV(string0).property(string1, string9).property(string3, number2).as(string9).addV(string0).property(string1, string10).property(string3, number3).as(string10).addV(string5).property(string1, string11).property(string7, string8).as(string11).addE(string12).from(string2).to(string4).addE(string12).from(string2).to(string9).addE(string13).from(string2).to(string6).addE(string13).from(string9).to(string6).addE(string13).from(string9).to(string11).addE(string13).from(string10).to(string6)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).As(\"peter\").AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE((string) \"knows\").From(\"marko\").To(\"vadas\").AddE((string) \"knows\").From(\"marko\").To(\"josh\").AddE((string) \"created\").From(\"marko\").To(\"lop\").AddE((string) \"created\").From(\"josh\").To(\"lop\").AddE((string) \"created\").From(\"josh\").To(\"ripple\").AddE((string) \"created\").From(\"peter\").To(\"lop\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).As(\"peter\").AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE(\"knows\").From(\"marko\").To(\"vadas\").AddE(\"knows\").From(\"marko\").To(\"josh\").AddE(\"created\").From(\"marko\").To(\"lop\").AddE(\"created\").From(\"josh\").To(\"lop\").AddE(\"created\").From(\"josh\").To(\"ripple\").AddE(\"created\").From(\"peter\").To(\"lop\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\").addE(\"created\").from(\"marko\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\").addE(\"created\").from(\"peter\").to(\"lop\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).as(\"peter\").addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"knows\").from_(\"marko\").to(\"vadas\").addE(\"knows\").from_(\"marko\").to(\"josh\").addE(\"created\").from_(\"marko\").to(\"lop\").addE(\"created\").from_(\"josh\").to(\"lop\").addE(\"created\").from_(\"josh\").to(\"ripple\").addE(\"created\").from_(\"peter\").to(\"lop\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).as_('peter').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh').add_e('created').from_('marko').to('lop').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple').add_e('created').from_('peter').to('lop')" + }, + { + "original": "g.V(vid2).property(__.V(vid1).project(\"friendCount\",\"softwareCreated\").by(__.out(\"knows\").count()).by(__.out(\"created\").values(\"name\")))", + "language": "g.V(vid2).property(__.V(vid1).project(\"friendCount\", \"softwareCreated\").by(__.out(\"knows\").count()).by(__.out(\"created\").values(\"name\")))", + "canonical": "g.V(vid2).property(__.V(vid1).project(\"friendCount\", \"softwareCreated\").by(__.out(\"knows\").count()).by(__.out(\"created\").values(\"name\")))", + "anonymized": "g.V(vid2).property(__.V(vid1).project(string0, string1).by(__.out(string2).count()).by(__.out(string3).values(string4)))", + "dotnet": "g.V(vid2).Property((ITraversal) __.V(vid1).Project(\"friendCount\", \"softwareCreated\").By(__.Out(\"knows\").Count()).By(__.Out(\"created\").Values(\"name\")))", + "go": "g.V(vid2).Property(gremlingo.T__.V(vid1).Project(\"friendCount\", \"softwareCreated\").By(gremlingo.T__.Out(\"knows\").Count()).By(gremlingo.T__.Out(\"created\").Values(\"name\")))", + "groovy": "g.V(vid2).property(__.V(vid1).project(\"friendCount\", \"softwareCreated\").by(__.out(\"knows\").count()).by(__.out(\"created\").values(\"name\")))", + "java": "g.V(vid2).property(__.V(vid1).project(\"friendCount\", \"softwareCreated\").by(__.out(\"knows\").count()).by(__.out(\"created\").values(\"name\")))", + "javascript": "g.V(vid2).property(__.V(vid1).project(\"friendCount\", \"softwareCreated\").by(__.out(\"knows\").count()).by(__.out(\"created\").values(\"name\")))", + "python": "g.V(vid2).property(__.V(vid1).project('friendCount', 'softwareCreated').by(__.out('knows').count()).by(__.out('created').values('name')))" + }, + { + "original": "g.V().has(\"friendCount\", 2L)", + "language": "g.V().has(\"friendCount\", 2l)", + "canonical": "g.V().has(\"friendCount\", 2l)", + "anonymized": "g.V().has(string0, long0)", + "dotnet": "g.V().Has(\"friendCount\", 2l)", + "go": "g.V().Has(\"friendCount\", int64(2))", + "groovy": "g.V().has(\"friendCount\", 2l)", + "java": "g.V().has(\"friendCount\", 2l)", + "javascript": "g.V().has(\"friendCount\", 2)", + "python": "g.V().has('friendCount', long(2))" + }, + { + "original": "g.V().has(\"softwareCreated\", \"lop\")", + "language": "g.V().has(\"softwareCreated\", \"lop\")", + "canonical": "g.V().has(\"softwareCreated\", \"lop\")", + "anonymized": "g.V().has(string0, string1)", + "dotnet": "g.V().Has(\"softwareCreated\", \"lop\")", + "go": "g.V().Has(\"softwareCreated\", \"lop\")", + "groovy": "g.V().has(\"softwareCreated\", \"lop\")", + "java": "g.V().has(\"softwareCreated\", \"lop\")", + "javascript": "g.V().has(\"softwareCreated\", \"lop\")", + "python": "g.V().has('softwareCreated', 'lop')" + } + ] + }, + { + "scenario": "g_VXvid2X_propertyXVXvid1X_projectXoriginalName_originalLabelX_byXnameX_byXlabelXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).as(\"marko\").addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").as(\"lop\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).as(string2).addV(string0).property(string1, string4).property(string3, number1).addV(string5).property(string1, string6).property(string7, string8).as(string6).addV(string0).property(string1, string9).property(string3, number2).addV(string0).property(string1, string10).property(string3, number3).addV(string5).property(string1, string11).property(string7, string8)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java')" + }, + { + "original": "g.V(vid2).property(__.V(vid1).project(\"originalName\",\"originalLabel\").by(__.values(\"name\")).by(__.label()))", + "language": "g.V(vid2).property(__.V(vid1).project(\"originalName\", \"originalLabel\").by(__.values(\"name\")).by(__.label()))", + "canonical": "g.V(vid2).property(__.V(vid1).project(\"originalName\", \"originalLabel\").by(__.values(\"name\")).by(__.label()))", + "anonymized": "g.V(vid2).property(__.V(vid1).project(string0, string1).by(__.values(string2)).by(__.label()))", + "dotnet": "g.V(vid2).Property((ITraversal) __.V(vid1).Project(\"originalName\", \"originalLabel\").By(__.Values(\"name\")).By(__.Label()))", + "go": "g.V(vid2).Property(gremlingo.T__.V(vid1).Project(\"originalName\", \"originalLabel\").By(gremlingo.T__.Values(\"name\")).By(gremlingo.T__.Label()))", + "groovy": "g.V(vid2).property(__.V(vid1).project(\"originalName\", \"originalLabel\").by(__.values(\"name\")).by(__.label()))", + "java": "g.V(vid2).property(__.V(vid1).project(\"originalName\", \"originalLabel\").by(__.values(\"name\")).by(__.label()))", + "javascript": "g.V(vid2).property(__.V(vid1).project(\"originalName\", \"originalLabel\").by(__.values(\"name\")).by(__.label()))", + "python": "g.V(vid2).property(__.V(vid1).project('originalName', 'originalLabel').by(__.values('name')).by(__.label()))" + }, + { + "original": "g.V(vid2).has(\"originalName\", \"marko\")", + "language": "g.V(vid2).has(\"originalName\", \"marko\")", + "canonical": "g.V(vid2).has(\"originalName\", \"marko\")", + "anonymized": "g.V(vid2).has(string0, string1)", + "dotnet": "g.V(vid2).Has(\"originalName\", \"marko\")", + "go": "g.V(vid2).Has(\"originalName\", \"marko\")", + "groovy": "g.V(vid2).has(\"originalName\", \"marko\")", + "java": "g.V(vid2).has(\"originalName\", \"marko\")", + "javascript": "g.V(vid2).has(\"originalName\", \"marko\")", + "python": "g.V(vid2).has('originalName', 'marko')" + }, + { + "original": "g.V(vid2).has(\"originalLabel\", \"person\")", + "language": "g.V(vid2).has(\"originalLabel\", \"person\")", + "canonical": "g.V(vid2).has(\"originalLabel\", \"person\")", + "anonymized": "g.V(vid2).has(string0, string1)", + "dotnet": "g.V(vid2).Has(\"originalLabel\", \"person\")", + "go": "g.V(vid2).Has(\"originalLabel\", \"person\")", + "groovy": "g.V(vid2).has(\"originalLabel\", \"person\")", + "java": "g.V(vid2).has(\"originalLabel\", \"person\")", + "javascript": "g.V(vid2).has(\"originalLabel\", \"person\")", + "python": "g.V(vid2).has('originalLabel', 'person')" + } + ] + }, + { + "scenario": "g_VXvid1X_propertyXlist_friends_outXknowsX_valuesXnameXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).as(\"marko\").addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).as(\"vadas\").addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).as(\"josh\").addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).as(string2).addV(string0).property(string1, string4).property(string3, number1).as(string4).addV(string5).property(string1, string6).property(string7, string8).addV(string0).property(string1, string9).property(string3, number2).as(string9).addV(string0).property(string1, string10).property(string3, number3).addV(string5).property(string1, string11).property(string7, string8).addE(string12).from(string2).to(string4).addE(string12).from(string2).to(string9)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").AddE((string) \"knows\").From(\"marko\").To(\"vadas\").AddE((string) \"knows\").From(\"marko\").To(\"josh\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").AddE(\"knows\").From(\"marko\").To(\"vadas\").AddE(\"knows\").From(\"marko\").To(\"josh\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from_(\"marko\").to(\"vadas\").addE(\"knows\").from_(\"marko\").to(\"josh\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh')" + }, + { + "original": "g.V(vid1).property(Cardinality.list, \"friends\", __.out(\"knows\").values(\"name\"))", + "language": "g.V(vid1).property(Cardinality.list, \"friends\", __.out(\"knows\").values(\"name\"))", + "canonical": "g.V(vid1).property(Cardinality.list, \"friends\", __.out(\"knows\").values(\"name\"))", + "anonymized": "g.V(vid1).property(Cardinality.list, string0, __.out(string1).values(string2))", + "dotnet": "g.V(vid1).Property(Cardinality.List, \"friends\", __.Out(\"knows\").Values(\"name\"))", + "go": "g.V(vid1).Property(gremlingo.Cardinality.List, \"friends\", gremlingo.T__.Out(\"knows\").Values(\"name\"))", + "groovy": "g.V(vid1).property(Cardinality.list, \"friends\", __.out(\"knows\").values(\"name\"))", + "java": "g.V(vid1).property(Cardinality.list, \"friends\", __.out(\"knows\").values(\"name\"))", + "javascript": "g.V(vid1).property(Cardinality.list, \"friends\", __.out(\"knows\").values(\"name\"))", + "python": "g.V(vid1).property(Cardinality.list_, 'friends', __.out('knows').values('name'))" + }, + { + "original": "g.V(vid1).properties(\"friends\")", + "language": "g.V(vid1).properties(\"friends\")", + "canonical": "g.V(vid1).properties(\"friends\")", + "anonymized": "g.V(vid1).properties(string0)", + "dotnet": "g.V(vid1).Properties(\"friends\")", + "go": "g.V(vid1).Properties(\"friends\")", + "groovy": "g.V(vid1).properties(\"friends\")", + "java": "g.V(vid1).properties(\"friends\")", + "javascript": "g.V(vid1).properties(\"friends\")", + "python": "g.V(vid1).properties('friends')" + } + ] + }, + { + "scenario": "g_VXvid1X_propertyXset_langs_outXcreatedX_valuesXlangXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").as(\"lop\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).as(\"josh\").addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\").as(\"ripple\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).addV(string0).property(string1, string4).property(string3, number1).addV(string5).property(string1, string6).property(string7, string8).as(string6).addV(string0).property(string1, string9).property(string3, number2).as(string9).addV(string0).property(string1, string10).property(string3, number3).addV(string5).property(string1, string11).property(string7, string8).as(string11).addE(string12).from(string9).to(string6).addE(string12).from(string9).to(string11)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE((string) \"created\").From(\"josh\").To(\"lop\").AddE((string) \"created\").From(\"josh\").To(\"ripple\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").As(\"lop\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").As(\"ripple\").AddE(\"created\").From(\"josh\").To(\"lop\").AddE(\"created\").From(\"josh\").To(\"ripple\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"created\").from(\"josh\").to(\"lop\").addE(\"created\").from(\"josh\").to(\"ripple\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").as(\"lop\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").as(\"ripple\").addE(\"created\").from_(\"josh\").to(\"lop\").addE(\"created\").from_(\"josh\").to(\"ripple\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27).add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_e('created').from_('josh').to('lop').add_e('created').from_('josh').to('ripple')" + }, + { + "original": "g.V(vid1).property(Cardinality.set, \"langs\", __.out(\"created\").values(\"lang\"))", + "language": "g.V(vid1).property(Cardinality.set, \"langs\", __.out(\"created\").values(\"lang\"))", + "canonical": "g.V(vid1).property(Cardinality.set, \"langs\", __.out(\"created\").values(\"lang\"))", + "anonymized": "g.V(vid1).property(Cardinality.set, string0, __.out(string1).values(string2))", + "dotnet": "g.V(vid1).Property(Cardinality.Set, \"langs\", __.Out(\"created\").Values(\"lang\"))", + "go": "g.V(vid1).Property(gremlingo.Cardinality.Set, \"langs\", gremlingo.T__.Out(\"created\").Values(\"lang\"))", + "groovy": "g.V(vid1).property(Cardinality.set, \"langs\", __.out(\"created\").values(\"lang\"))", + "java": "g.V(vid1).property(Cardinality.set, \"langs\", __.out(\"created\").values(\"lang\"))", + "javascript": "g.V(vid1).property(Cardinality.set, \"langs\", __.out(\"created\").values(\"lang\"))", + "python": "g.V(vid1).property(Cardinality.set_, 'langs', __.out('created').values('lang'))" + }, + { + "original": "g.V(vid1).properties(\"langs\")", + "language": "g.V(vid1).properties(\"langs\")", + "canonical": "g.V(vid1).properties(\"langs\")", + "anonymized": "g.V(vid1).properties(string0)", + "dotnet": "g.V(vid1).Properties(\"langs\")", + "go": "g.V(vid1).Properties(\"langs\")", + "groovy": "g.V(vid1).properties(\"langs\")", + "java": "g.V(vid1).properties(\"langs\")", + "javascript": "g.V(vid1).properties(\"langs\")", + "python": "g.V(vid1).properties('langs')" + } + ] + }, + { + "scenario": "g_VXvid1X_propertyXsingle_friend_outXknowsX_valuesXnameXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29).as(\"marko\").addV(\"person\").property(\"name\",\"vadas\").property(\"age\",27).as(\"vadas\").addV(\"software\").property(\"name\",\"lop\").property(\"lang\",\"java\").addV(\"person\").property(\"name\",\"josh\").property(\"age\",32).as(\"josh\").addV(\"person\").property(\"name\",\"peter\").property(\"age\",35).addV(\"software\").property(\"name\",\"ripple\").property(\"lang\",\"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0).as(string2).addV(string0).property(string1, string4).property(string3, number1).as(string4).addV(string5).property(string1, string6).property(string7, string8).addV(string0).property(string1, string9).property(string3, number2).as(string9).addV(string0).property(string1, string10).property(string3, number3).addV(string5).property(string1, string11).property(string7, string8).addE(string12).from(string2).to(string4).addE(string12).from(string2).to(string9)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV((string) \"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV((string) \"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV((string) \"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV((string) \"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV((string) \"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").AddE((string) \"knows\").From(\"marko\").To(\"vadas\").AddE((string) \"knows\").From(\"marko\").To(\"josh\")", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29).As(\"marko\").AddV(\"person\").Property(\"name\", \"vadas\").Property(\"age\", 27).As(\"vadas\").AddV(\"software\").Property(\"name\", \"lop\").Property(\"lang\", \"java\").AddV(\"person\").Property(\"name\", \"josh\").Property(\"age\", 32).As(\"josh\").AddV(\"person\").Property(\"name\", \"peter\").Property(\"age\", 35).AddV(\"software\").Property(\"name\", \"ripple\").Property(\"lang\", \"java\").AddE(\"knows\").From(\"marko\").To(\"vadas\").AddE(\"knows\").From(\"marko\").To(\"josh\")", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from(\"marko\").to(\"vadas\").addE(\"knows\").from(\"marko\").to(\"josh\")", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29).as(\"marko\").addV(\"person\").property(\"name\", \"vadas\").property(\"age\", 27).as(\"vadas\").addV(\"software\").property(\"name\", \"lop\").property(\"lang\", \"java\").addV(\"person\").property(\"name\", \"josh\").property(\"age\", 32).as(\"josh\").addV(\"person\").property(\"name\", \"peter\").property(\"age\", 35).addV(\"software\").property(\"name\", \"ripple\").property(\"lang\", \"java\").addE(\"knows\").from_(\"marko\").to(\"vadas\").addE(\"knows\").from_(\"marko\").to(\"josh\")", + "python": "g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('person').property('name', 'peter').property('age', 35).add_v('software').property('name', 'ripple').property('lang', 'java').add_e('knows').from_('marko').to('vadas').add_e('knows').from_('marko').to('josh')" + }, + { + "original": "g.V(vid1).property(Cardinality.single, \"friend\", __.out(\"knows\").values(\"name\"))", + "language": "g.V(vid1).property(Cardinality.single, \"friend\", __.out(\"knows\").values(\"name\"))", + "canonical": "g.V(vid1).property(Cardinality.single, \"friend\", __.out(\"knows\").values(\"name\"))", + "anonymized": "g.V(vid1).property(Cardinality.single, string0, __.out(string1).values(string2))", + "dotnet": "g.V(vid1).Property(Cardinality.Single, \"friend\", __.Out(\"knows\").Values(\"name\"))", + "go": "g.V(vid1).Property(gremlingo.Cardinality.Single, \"friend\", gremlingo.T__.Out(\"knows\").Values(\"name\"))", + "groovy": "g.V(vid1).property(Cardinality.single, \"friend\", __.out(\"knows\").values(\"name\"))", + "java": "g.V(vid1).property(Cardinality.single, \"friend\", __.out(\"knows\").values(\"name\"))", + "javascript": "g.V(vid1).property(Cardinality.single, \"friend\", __.out(\"knows\").values(\"name\"))", + "python": "g.V(vid1).property(Cardinality.single, 'friend', __.out('knows').values('name'))" + } + ] + }, + { + "scenario": "g_VXvid1X_propertyXVXvid1X_groupX_byXidX_byXvaluesXnameXXX", + "traversals": [ + { + "original": "g.addV(\"person\").property(\"name\",\"marko\").property(\"age\",29)", + "language": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29)", + "canonical": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29)", + "anonymized": "g.addV(string0).property(string1, string2).property(string3, number0)", + "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").Property(\"age\", 29)", + "go": "g.AddV(\"person\").Property(\"name\", \"marko\").Property(\"age\", 29)", + "groovy": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29)", + "java": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29)", + "javascript": "g.addV(\"person\").property(\"name\", \"marko\").property(\"age\", 29)", + "python": "g.add_v('person').property('name', 'marko').property('age', 29)" + }, + { + "original": "g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values(\"name\")))", + "language": "g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values(\"name\")))", + "canonical": "g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values(\"name\")))", + "anonymized": "g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values(string0)))", + "dotnet": "g.V(vid1).Property((ITraversal) __.V(vid1).Group().By(__.Id()).By(__.Values(\"name\")))", + "go": "g.V(vid1).Property(gremlingo.T__.V(vid1).Group().By(gremlingo.T__.Id()).By(gremlingo.T__.Values(\"name\")))", + "groovy": "g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values(\"name\")))", + "java": "g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values(\"name\")))", + "javascript": "g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values(\"name\")))", + "python": "g.V(vid1).property(__.V(vid1).group().by(__.id_()).by(__.values('name')))" + } + ] + }, { "scenario": "g_io_readXkryoX", "traversals": [ 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 b60932ce8e9..e559148f4b5 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 @@ -620,4 +620,409 @@ Feature: Step - has() g.V().has("name", null) """ When iterated to list - Then the result should be empty \ No newline at end of file + Then the result should be empty + + Scenario: g_V_hasXname_constantXmarkoXX + Given the modern graph + And the traversal of + """ + g.V().has("name", __.constant("marko")) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + + @GraphComputerVerificationMidVNotSupported + # has(key, traversal) with multi-result child traversal - takes first result (order-dependent) + Scenario: g_V_hasXname_VXvid1X_outXknowsX_valuesXnameXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().has("name", __.V(vid1).out("knows").values("name").order()) + """ + When iterated to list + Then the result should be unordered + | result | + | v[josh] | + + Scenario: g_V_hasXname_valuesXnonexistentXX + Given the modern graph + And the traversal of + """ + g.V().has("name", __.values("nonexistent")) + """ + When iterated to list + Then the result should be empty + + Scenario: g_V_hasXname_notXidentityXX + Given the modern graph + And the traversal of + """ + g.V().has("name", __.not(__.identity())) + """ + When iterated to list + Then the result should be empty + + Scenario: g_V_hasXage_gtXconstantX29XXX + Given the modern graph + And the traversal of + """ + g.V().has("age", P.gt(__.constant(29))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[josh] | + | v[peter] | + + Scenario: g_V_hasXage_lteXconstantX27XXX + Given the modern graph + And the traversal of + """ + g.V().has("age", P.lte(__.constant(27))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[vadas] | + + Scenario: g_V_hasXage_neqXconstantX32XXX + Given the modern graph + And the traversal of + """ + g.V().has("age", P.neq(__.constant(32))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + | v[vadas] | + | v[peter] | + + Scenario: g_V_hasXname_eqXconstantXmarkoXXX + Given the modern graph + And the traversal of + """ + g.V().has("name", P.eq(__.constant("marko"))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + + Scenario: g_V_hasXage_ltXconstantX29XXX + Given the modern graph + And the traversal of + """ + g.V().has("age", P.lt(__.constant(29))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[vadas] | + + Scenario: g_V_hasXage_gteXconstantX32XXX + Given the modern graph + And the traversal of + """ + g.V().has("age", P.gte(__.constant(32))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[josh] | + | v[peter] | + + Scenario: g_V_hasXage_eqXvaluesXnonexistentXXX + Given the modern graph + And the traversal of + """ + g.V().has("age", P.eq(__.values("nonexistent"))) + """ + When iterated to list + Then the result should be empty + + Scenario: g_V_hasXlabel_constantXpersonXX + Given the modern graph + And the traversal of + """ + g.V().has(T.label, __.constant("person")) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + | v[vadas] | + | v[josh] | + | v[peter] | + + Scenario: g_V_hasXperson_name_constantXmarkoXX_age + Given the modern graph + And the traversal of + """ + g.V().has("person", "name", __.constant("marko")).values("age") + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | + + # within() over a union of relationship results collected with fold() - one traversal, one collection + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_constantXpeterXX_foldXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().has("name", P.within(__.union(__.V(vid1).out("knows").values("name"), __.constant("peter")).fold())) + """ + When iterated to list + Then the result should be unordered + | result | + | v[vadas] | + | v[josh] | + | v[peter] | + + # Multi-traversal within() where one traversal produces no results - still matches on the other + Scenario: g_V_hasXname_withinXvaluesXnonexistentX_constantXmarkoXXX + Given the modern graph + And the traversal of + """ + g.V().has("name", P.within(__.values("nonexistent"), __.constant("marko"))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + + # Multi-traversal within() where all traversals produce no results - filters everything + Scenario: g_V_hasXname_withinXvaluesXnonexistentX_valuesXnonexistent2XXX + Given the modern graph + And the traversal of + """ + g.V().has("name", P.within(__.values("nonexistent"), __.values("nonexistent2"))) + """ + When iterated to list + Then the result should be empty + + # Multi-traversal without() with three constant traversals + Scenario: g_V_hasXname_withoutXconstantXmarkoX_constantXvadasX_constantXpeterXXX + Given the modern graph + And the traversal of + """ + g.V().has("name", P.without(__.constant("marko"), __.constant("vadas"), __.constant("peter"))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[josh] | + | v[lop] | + | v[ripple] | + + # within() over a union of relationship traversals from different sources, collected with fold() + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasXname_withinXunionXVXvid1X_outXknowsX_valuesXnameX_VXvid3X_outXcreatedX_valuesXnameXX_foldXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And using the parameter vid3 defined as "v[josh].id" + And the traversal of + """ + g.V().has("name", P.within(__.union(__.V(vid1).out("knows").values("name"), + __.V(vid3).out("created").values("name")).fold())) + """ + When iterated to list + Then the result should be unordered + | result | + | v[vadas] | + | v[josh] | + | v[ripple] | + | v[lop] | + + # without() over a union of relationship sources collected with fold() + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasLabelXsoftwareX_hasXname_withoutXunionXVXvid1X_outXcreatedX_valuesXnameX_VXvid4X_outXcreatedX_valuesXnameXX_foldXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And using the parameter vid4 defined as "v[josh].id" + And the traversal of + """ + g.V().hasLabel("software"). + has("name", P.without(__.union(__.V(vid1).out("created").values("name"), + __.V(vid4).out("created").values("name")).fold())) + """ + When iterated to list + Then the result should be empty + + # within() with is() - cross-label dynamic filtering using a union collected with fold() + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasLabelXpersonX_valuesXageX_isXwithinXunionXVXvid1X_valuesXageX_V_hasXname_lopX_inXcreatedX_valuesXageXX_foldXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().hasLabel("person").values("age"). + is(P.within(__.union(__.V(vid1).values("age"), + __.V().has("name","lop").in("created").values("age")).fold())) + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | + | d[32].i | + | d[35].i | + + # within() - dynamic edge filtering via inV property check using a union collected with fold() + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_outEXknowsX_filterXinV_hasXname_withinXunionXV_hasXname_lopX_inXcreatedX_valuesXnameX_V_hasXname_rippleX_inXcreatedX_valuesXnameXX_foldXXXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).outE("knows"). + filter(__.inV().has("name", P.within(__.union(__.V().has("name","lop").in("created").values("name"), + __.V().has("name","ripple").in("created").values("name")).fold()))) + """ + When iterated to list + Then the result should be unordered + | result | + | e[marko-knows->josh] | + + # hasLabel with a child traversal + Scenario: g_V_hasLabelXconstantXpersonXX + Given the modern graph + And the traversal of + """ + g.V().hasLabel(__.constant("person")) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + | v[vadas] | + | v[josh] | + | v[peter] | + + # hasId with P.eq(traversal) + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasIdXeqXVXvid1X_idXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().hasId(P.eq(__.V(vid1).id())) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + + # hasId with traversal passed directly + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasIdXVXvid1X_idXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().hasId(__.V(vid1).id()) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + + # hasKey with a child traversal + Scenario: g_V_propertiesXageX_hasKeyXconstantXageXX + Given the modern graph + And the traversal of + """ + g.V().properties("age").hasKey(__.constant("age")) + """ + When iterated to list + Then the result should be unordered + | result | + | vp[marko-age->d[29].i] | + | vp[vadas-age->d[27].i] | + | vp[josh-age->d[32].i] | + | vp[peter-age->d[35].i] | + + # hasKey with P.eq(traversal) + Scenario: g_V_propertiesXageX_hasKeyXeqXconstantXageXXX + Given the modern graph + And the traversal of + """ + g.V().properties("age").hasKey(P.eq(__.constant("age"))) + """ + When iterated to list + Then the result should be unordered + | result | + | vp[marko-age->d[29].i] | + | vp[vadas-age->d[27].i] | + | vp[josh-age->d[32].i] | + | vp[peter-age->d[35].i] | + + # hasValue with a child traversal + Scenario: g_V_propertiesXageX_hasValueXconstantX29XX + Given the modern graph + And the traversal of + """ + g.V().properties("age").hasValue(__.constant(29)) + """ + When iterated to list + Then the result should be unordered + | result | + | vp[marko-age->d[29].i] | + + # hasValue with P.eq(traversal) + Scenario: g_V_propertiesXageX_hasValueXeqXconstantX29XXX + Given the modern graph + And the traversal of + """ + g.V().properties("age").hasValue(P.eq(__.constant(29))) + """ + When iterated to list + Then the result should be unordered + | result | + | vp[marko-age->d[29].i] | + + # Child traversal using select() to reference a labeled step value + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_asXaX_V_hasXage_gtXselectXaX_valuesXageXXX_valuesXnameX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).as("a").V().has("age", P.gt(__.select("a").values("age"))).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | josh | + | peter | + + # Child traversal using sack() to filter against the traverser's sack value + Scenario: g_withSackX29X_V_hasXage_gtXsackXX_valuesXnameX + Given the modern graph + And the traversal of + """ + g.withSack(29).V().has("age", P.gt(__.sack())).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | josh | + | peter | + + # Child traversal using constant() to filter edge properties + Scenario: g_V_hasXname_markoX_outEXknowsX_hasXweight_gteXconstantX05XXX + Given the modern graph + And the traversal of + """ + g.V().has("name","marko").outE("knows").has("weight", P.gte(__.constant(0.5))) + """ + When iterated to list + Then the result should be unordered + | result | + | e[marko-knows->vadas] | + | e[marko-knows->josh] | diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature index cdf8c0e8d99..93afd854b96 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature @@ -112,4 +112,264 @@ Feature: Step - is() When iterated to list Then the result should be unordered | result | - | lop | \ No newline at end of file + | lop | + Scenario: g_V_valuesXageX_isXconstantX29XX + Given the modern graph + And the traversal of + """ + g.V().values("age").is(__.constant(29)) + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | + + Scenario: g_V_valuesXnameX_isXconstantXmarkoXX + Given the modern graph + And the traversal of + """ + g.V().values("name").is(__.constant("marko")) + """ + When iterated to list + Then the result should be unordered + | result | + | marko | + + Scenario: g_V_valuesXageX_isXgtXconstantX29XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").is(P.gt(__.constant(29))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[32].i | + | d[35].i | + + Scenario: g_V_valuesXageX_isXltXconstantX32XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").is(P.lt(__.constant(32))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | + | d[27].i | + + Scenario: g_V_valuesXageX_isXneqXconstantX35XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").is(P.neq(__.constant(35))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | + | d[27].i | + | d[32].i | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_valuesXageX_isXwithinXVXvid1X_outXknowsX_valuesXageXXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().values("age").is(P.within(__.V(vid1).out("knows").values("age").fold())) + """ + When iterated to list + Then the result should be unordered + | result | + | d[27].i | + | d[32].i | + + Scenario: g_V_valuesXageX_isXconstantX99999XX + Given the modern graph + And the traversal of + """ + g.V().values("age").is(__.constant(99999)) + """ + When iterated to list + Then the result should be empty + + Scenario: g_V_hasLabelXpersonX_valuesXageX_chooseXgtXconstantX29XX_olderX + Given the modern graph + And the traversal of + """ + g.V().hasLabel("person").values("age"). + choose(__.is(P.gt(__.constant(29))), + __.constant("older than marko"), + __.constant("not older")) + """ + When iterated to list + Then the result should be unordered + | result | + | not older | + | not older | + | older than marko | + | older than marko | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasLabelXpersonX_valuesXageX_chooseXgteXmeanAgeX_aboveX + Given the modern graph + And the traversal of + """ + g.V().hasLabel("person").values("age"). + choose(__.is(P.gte(__.V().hasLabel("person").values("age").mean())), + __.constant("above average"), + __.constant("below average")) + """ + When iterated to list + Then the result should be unordered + | result | + | below average | + | below average | + | above average | + | above average | + + Scenario: g_VXvid1X_outXknowsX_valuesXageX_fold_allXgteXconstantX27XXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).out("knows").values("age").fold().all(P.gte(__.constant(27))) + """ + When iterated to list + Then the result should have a count of 1 + + Scenario: g_VXvid1X_outXknowsX_valuesXageX_fold_allXgtXconstantX27XXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).out("knows").values("age").fold().all(P.gt(__.constant(27))) + """ + When iterated to list + Then the result should be empty + + Scenario: g_VXvid1X_outXknowsX_valuesXageX_fold_anyXeqXconstantX32XXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).out("knows").values("age").fold().any(P.eq(__.constant(32))) + """ + When iterated to list + Then the result should have a count of 1 + + Scenario: g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX35XXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).out("knows").values("age").fold().none(P.eq(__.constant(35))) + """ + When iterated to list + Then the result should have a count of 1 + + Scenario: g_VXvid1X_outXknowsX_valuesXageX_fold_noneXeqXconstantX32XXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).out("knows").values("age").fold().none(P.eq(__.constant(32))) + """ + When iterated to list + Then the result should be empty + + # Empty-result handling: predicate should treat "no results" as "no match", not null. + @GraphComputerVerificationMidVNotSupported + Scenario: g_injectXnullX_isXeqXV9999_valuesXnameXXX + Given the modern graph + And the traversal of + """ + g.inject(null).is(P.eq(__.V(9999).values("name"))) + """ + When iterated to list + Then the result should be empty + + @GraphComputerVerificationMidVNotSupported + Scenario: g_injectXmarkoX_isXV9999_valuesXnameXX + Given the modern graph + And the traversal of + """ + g.inject("marko").is(__.V(9999).values("name")) + """ + When iterated to list + Then the result should be empty + + @GraphComputerVerificationMidVNotSupported + Scenario: g_injectXmarkoX_chooseXeqXV9999_valuesXnameXX_matched_unmatchedX + Given the modern graph + And the traversal of + """ + g.inject("marko").choose(__.is(P.eq(__.V(9999).values("name"))), __.constant("matched"), __.constant("unmatched")) + """ + When iterated to list + Then the result should be unordered + | result | + | unmatched | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_injectXlistX_noneXeqXV9999_valuesXnameXXX + Given the modern graph + And the traversal of + """ + g.inject(["marko","josh"]).none(P.eq(__.V(9999).values("name"))) + """ + When iterated to list + Then the result should have a count of 1 + + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasXname_eqXV9999_valuesXnameXXX + Given the modern graph + And the traversal of + """ + g.V().has("name", P.eq(__.V(9999).values("name"))) + """ + When iterated to list + Then the result should be empty + + # Multi-traversal without() in is() context + Scenario: g_V_valuesXageX_isXwithoutXconstantX29X_constantX32XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").is(P.without(__.constant(29), __.constant(32))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[27].i | + | d[35].i | + + # Child traversal using select() to reference a labeled step value + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_asXaX_V_valuesXageX_isXgtXselectXaX_valuesXageXXX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).as("a").V().values("age").is(P.gt(__.select("a").values("age"))) + """ + When iterated to list + Then the result should be unordered + | result | + | d[32].i | + | d[35].i | + + # Child traversal using sack() to filter against the traverser's sack value + Scenario: g_withSackX30X_V_valuesXageX_isXgtXsackXX + Given the modern graph + And the traversal of + """ + g.withSack(30).V().values("age").is(P.gt(__.sack())) + """ + When iterated to list + Then the result should be unordered + | result | + | d[32].i | + | d[35].i | diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature index 3f8443e70e9..32812c9ee52 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature @@ -446,3 +446,148 @@ Feature: Step - where() | v[vadas] | | v[josh] | | v[peter] | + + # where(P.gt(traversal)) - compare current traverser value against resolved traversal result + @GraphComputerVerificationStarGraphExceeded + Scenario: g_V_valuesXageX_whereXgtXconstantX29XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").where(P.gt(__.constant(29))) + """ + 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 a constant + @GraphComputerVerificationStarGraphExceeded + Scenario: g_V_valuesXageX_whereXltXconstantX32XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").where(P.lt(__.constant(32))) + """ + 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 + @GraphComputerVerificationStarGraphExceeded + Scenario: g_V_valuesXageX_whereXeqXconstantX29XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").where(P.eq(__.constant(29))) + """ + 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").fold())) + """ + 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 + @GraphComputerVerificationStarGraphExceeded + Scenario: g_V_valuesXnameX_whereXneqXconstantXmarkoXXX + Given the modern graph + And the traversal of + """ + g.V().values("name").where(P.neq(__.constant("marko"))) + """ + When iterated to list + Then the result should be unordered + | result | + | vadas | + | lop | + | josh | + | ripple | + | peter | + + # Empty traversal result - filters out (no match) + @GraphComputerVerificationStarGraphExceeded + Scenario: g_V_valuesXageX_whereXeqXconstantX99999XXX + Given the modern graph + And the traversal of + """ + g.V().values("age").where(P.eq(__.constant(99999))) + """ + 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 | + + # Mixed ConnectiveP: traversal-bearing predicate AND scope-label predicate + # Verifies that scope-label resolution still works when combined with traversal predicates + @GraphComputerVerificationMidVNotSupported + Scenario: g_VX1X_asXaX_V_valuesXageX_whereXgteXconstantX0XX_andXneqXaXXX_byX_byXageX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).as("a").V().hasLabel("person").values("age").where(P.gte(__.constant(0)).and(P.neq("a"))).by().by("age") + """ + When iterated to list + Then the result should be unordered + | result | + | d[27].i | + | d[32].i | + | d[35].i | + + # Mixed ConnectiveP: scope-label predicate AND traversal-bearing predicate (reversed order) + @GraphComputerVerificationMidVNotSupported + Scenario: g_VX1X_asXaX_V_valuesXageX_whereXneqXaX_andXgtXVXvid1X_valuesXageXXXX_byX_byXageX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).as("a").V().hasLabel("person").values("age").where(P.neq("a").and(P.gt(__.V(vid1).values("age")))).by().by("age") + """ + When iterated to list + Then the result should be unordered + | result | + | d[32].i | + | d[35].i | + + # Mixed ConnectiveP with OR: traversal OR scope-label + @GraphComputerVerificationMidVNotSupported + Scenario: g_VX1X_asXaX_V_valuesXageX_whereXeqXVXvid1X_valuesXageXX_orXeqXaXXX_byX_byXageX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).as("a").V().hasLabel("person").values("age").where(P.eq(__.V(vid1).values("age")).or(P.eq("a"))).by().by("age") + """ + When iterated to list + Then the result should be unordered + | result | + | d[29].i | diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/StandardVerificationStrategy.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/StandardVerificationStrategy.feature index febc1119158..888492fc13e 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/StandardVerificationStrategy.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/StandardVerificationStrategy.feature @@ -50,3 +50,179 @@ Feature: Step - StandardVerificationStrategy | v[josh] | | v[ripple] | | v[peter] | + + # ===== Read-only child traversal validation ===== + # StandardVerificationStrategy rejects mutating steps inside child traversals of ReadOnlyTraversalParent steps. + + # ===== FILTER CONTEXT: has() with mutating child traversals ===== + + Scenario: g_V_hasXname_addVXxX_valuesXnameXX_rejected + Given the modern graph + And the traversal of + """ + g.V().has("name", __.addV("x").values("name")) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_hasXname_V_drop_constantXxXX_rejected + Given the modern graph + And the traversal of + """ + g.V().has("name", __.V().drop().constant("x")) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_hasXname_V_mapXaddVXxXX_valuesXnameXX_rejected + Given the modern graph + And the traversal of + """ + g.V().has("name", __.V().map(__.addV("x")).values("name")) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_hasXname_eqXaddVXxX_valuesXnameXXX_rejected + Given the modern graph + And the traversal of + """ + g.V().has("name", P.eq(__.addV("x").values("name"))) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_hasXname_withinXaddVXxX_valuesXnameXXX_rejected + Given the modern graph + And the traversal of + """ + g.V().has("name", P.within(__.addV("x").values("name"))) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_hasXage_gtXaddVXxX_valuesXageXXX_rejected + Given the modern graph + And the traversal of + """ + g.V().has("age", P.gt(__.addV("x").values("age"))) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + # ===== FILTER CONTEXT: is() with mutating child traversals ===== + + Scenario: g_V_valuesXageX_isXaddVXxX_valuesXageXX_rejected + Given the modern graph + And the traversal of + """ + g.V().values("age").is(__.addV("x").values("age")) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_valuesXageX_isXgtXaddVXxX_valuesXageXXX_rejected + Given the modern graph + And the traversal of + """ + g.V().values("age").is(P.gt(__.addV("x").values("age"))) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + # ===== LOOKUP CONTEXT: V()/E() with mutating child traversals ===== + + Scenario: g_V_VXaddVXxX_idX_rejected + Given the modern graph + And the traversal of + """ + g.V().V(__.addV("x").id()) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_EXaddVXxX_idX_rejected + Given the modern graph + And the traversal of + """ + g.V().E(__.addV("x").id()) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_VXaddVXxX_idX_rejected + Given the modern graph + And the traversal of + """ + g.V(__.addV("x").id()) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_EXaddVXxX_idX_rejected + Given the modern graph + And the traversal of + """ + g.E(__.addV("x").id()) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected + Given the modern graph + And the traversal of + """ + g.V().property(__.V().map(__.drop()).project("x").by("name")) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + Scenario: g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected + Given the modern graph + And the traversal of + """ + g.V().property(__.addV("temp").project("k").by("name")) + """ + When iterated to list + Then the traversal will raise an error with message containing text of "mutating step" + + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().has("name", __.V(vid1).values("name")) + """ + When iterated to list + Then the result should be unordered + | result | + | v[marko] | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V().has("age", P.gt(__.V(vid1).values("age"))) + """ + When iterated to list + Then the result should be unordered + | result | + | v[josh] | + | v[peter] | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).V(__.out("knows").id()).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | vadas | + | josh | diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature index 34eace5d056..670476742a4 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature @@ -362,4 +362,57 @@ Feature: Step - E(), inV(), outV(), bothV(), otherV() Then the result should be unordered | result | | d[0.5].d | - | d[1.0].d | \ No newline at end of file + | d[1.0].d | + + @GraphComputerVerificationMidENotSupported + Scenario: g_VXvid1X_EXoutE_idX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).E(__.outE().id()) + """ + When iterated to list + Then the result should be unordered + | result | + | e[marko-created->lop] | + | e[marko-knows->josh] | + | e[marko-knows->vadas] | + + @GraphComputerVerificationMidENotSupported + Scenario: g_VXvid1X_outEXknowsX_hasXinV_name_vadasX_id_EXidentityX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).outE("knows").filter(__.inV().has("name","vadas")).id().E(__.identity()) + """ + When iterated to list + Then the result should be unordered + | result | + | e[marko-knows->vadas] | + + @GraphComputerVerificationMidENotSupported + Scenario: g_injectX9999X_EXidentityX + Given the modern graph + And the traversal of + """ + g.inject(9999).E(__.identity()) + """ + When iterated to list + Then the result should be empty + + @GraphComputerVerificationMidVNotSupported + Scenario: g_EXVXvid1X_outE_idX + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.E(__.V(vid1).outE().id()) + """ + When iterated to list + Then the result should be unordered + | result | + | e[marko-created->lop] | + | e[marko-knows->josh] | + | e[marko-knows->vadas] | diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature index ee788c8117b..f9218ee462f 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature @@ -540,4 +540,84 @@ Feature: Step - V(), out(), in(), both(), inE(), outE(), bothE() And the graph should return 4 for count of "g.V(vid3).inE(\"uses\")" And the graph should return 2 for count of "g.V(vid4).outE(\"uses\")" And the graph should return 4 for count of "g.V(vid5).inE(\"uses\")" - And the graph should return 2 for count of "g.V(vid6).outE(\"uses\")" \ No newline at end of file + And the graph should return 2 for count of "g.V(vid6).outE(\"uses\")" + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_id_VXidentityX_name + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).id().V(__.identity()).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | marko | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1_vid2X_id_VXidentityX_name + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And using the parameter vid2 defined as "v[josh].id" + And the traversal of + """ + g.V(vid1, vid2).id().V(__.identity()).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | marko | + | josh | + + # Use as()/select() to bookmark a vertex ID and return to it later via V(select()). + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_id_asXbookmarkX_V_hasXname_joshX_VXselectXbookmarkXX_name + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).id().as("bookmark").V().has("name","josh").V(__.select("bookmark")).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | marko | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_VXoutXknowsX_idX_name + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).V(__.out("knows").id()).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | vadas | + | josh | + + @GraphComputerVerificationMidVNotSupported + Scenario: g_injectX9999X_VXidentityX + Given the modern graph + And the traversal of + """ + g.inject(9999).V(__.identity()) + """ + When iterated to list + Then the result should be empty + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXVXvid1X_idX_name + Given the modern graph + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(__.V(vid1).id()).values("name") + """ + When iterated to list + Then the result should be unordered + | result | + | marko | + diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Property.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Property.feature new file mode 100644 index 00000000000..896a443d3a2 --- /dev/null +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Property.feature @@ -0,0 +1,248 @@ +# 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. + +@StepClassSideEffect @StepAddProperty +Feature: Step - property() + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid2X_propertyXalias_VXvid1X_valuesXnameXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29). + addV("person").property("name","vadas").property("age",27). + addV("software").property("name","lop").property("lang","java"). + addV("person").property("name","josh").property("age",32). + addV("person").property("name","peter").property("age",35). + addV("software").property("name","ripple").property("lang","java") + """ + And using the parameter vid1 defined as "v[marko].id" + And using the parameter vid2 defined as "v[josh].id" + And the traversal of + """ + g.V(vid2).property("alias", __.V(vid1).values("name")) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 1 for count of "g.V().has(\"alias\", \"marko\")" + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_propertyXcreatorCount_VXvid1X_inXcreatedX_countX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29).as("marko"). + addV("person").property("name","vadas").property("age",27). + addV("software").property("name","lop").property("lang","java").as("lop"). + addV("person").property("name","josh").property("age",32).as("josh"). + addV("person").property("name","peter").property("age",35).as("peter"). + addV("software").property("name","ripple").property("lang","java").as("ripple"). + addE("knows").from("marko").to(__.V().has("name","vadas")). + addE("knows").from("marko").to("josh"). + addE("created").from("marko").to("lop"). + addE("created").from("josh").to("lop"). + addE("created").from("josh").to("ripple"). + addE("created").from("peter").to("lop") + """ + And using the parameter vid1 defined as "v[lop].id" + And the traversal of + """ + g.V(vid1).property("creatorCount", __.V(vid1).in("created").count()) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 1 for count of "g.V().has(\"creatorCount\", 3L)" + + Scenario: g_VXvid1X_propertyXknownCount_outXknowsX_countX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29).as("marko"). + addV("person").property("name","vadas").property("age",27).as("vadas"). + addV("software").property("name","lop").property("lang","java"). + addV("person").property("name","josh").property("age",32).as("josh"). + addV("person").property("name","peter").property("age",35). + addV("software").property("name","ripple").property("lang","java"). + addE("knows").from("marko").to("vadas"). + addE("knows").from("marko").to("josh") + """ + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).property("knownCount", __.out("knows").count()) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 1 for count of "g.V().has(\"knownCount\", 2L)" + + Scenario: g_VXvid1X_propertyXcreator_inXcreatedX_valuesXnameXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29).as("marko"). + addV("person").property("name","vadas").property("age",27). + addV("software").property("name","lop").property("lang","java").as("lop"). + addV("person").property("name","josh").property("age",32).as("josh"). + addV("person").property("name","peter").property("age",35).as("peter"). + addV("software").property("name","ripple").property("lang","java").as("ripple"). + addE("knows").from("marko").to(__.V().has("name","vadas")). + addE("knows").from("marko").to("josh"). + addE("created").from("marko").to("lop"). + addE("created").from("josh").to("lop"). + addE("created").from("josh").to("ripple"). + addE("created").from("peter").to("lop") + """ + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).property("creator", __.in("created").values("name")) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 0 for count of "g.V().has(\"creator\")" + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid2X_propertyXVXvid1X_projectXfriendCount_softwareCreatedXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29).as("marko"). + addV("person").property("name","vadas").property("age",27).as("vadas"). + addV("software").property("name","lop").property("lang","java").as("lop"). + addV("person").property("name","josh").property("age",32).as("josh"). + addV("person").property("name","peter").property("age",35).as("peter"). + addV("software").property("name","ripple").property("lang","java").as("ripple"). + addE("knows").from("marko").to("vadas"). + addE("knows").from("marko").to("josh"). + addE("created").from("marko").to("lop"). + addE("created").from("josh").to("lop"). + addE("created").from("josh").to("ripple"). + addE("created").from("peter").to("lop") + """ + And using the parameter vid1 defined as "v[marko].id" + And using the parameter vid2 defined as "v[josh].id" + And the traversal of + """ + g.V(vid2).property(__.V(vid1).project("friendCount","softwareCreated").by(__.out("knows").count()).by(__.out("created").values("name"))) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 1 for count of "g.V().has(\"friendCount\", 2L)" + And the graph should return 1 for count of "g.V().has(\"softwareCreated\", \"lop\")" + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid2X_propertyXVXvid1X_projectXoriginalName_originalLabelX_byXnameX_byXlabelXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29).as("marko"). + addV("person").property("name","vadas").property("age",27). + addV("software").property("name","lop").property("lang","java").as("lop"). + addV("person").property("name","josh").property("age",32). + addV("person").property("name","peter").property("age",35). + addV("software").property("name","ripple").property("lang","java") + """ + And using the parameter vid1 defined as "v[marko].id" + And using the parameter vid2 defined as "v[lop].id" + And the traversal of + """ + g.V(vid2).property(__.V(vid1).project("originalName","originalLabel").by(__.values("name")).by(__.label())) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 1 for count of "g.V(vid2).has(\"originalName\", \"marko\")" + And the graph should return 1 for count of "g.V(vid2).has(\"originalLabel\", \"person\")" + + Scenario: g_VXvid1X_propertyXlist_friends_outXknowsX_valuesXnameXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29).as("marko"). + addV("person").property("name","vadas").property("age",27).as("vadas"). + addV("software").property("name","lop").property("lang","java"). + addV("person").property("name","josh").property("age",32).as("josh"). + addV("person").property("name","peter").property("age",35). + addV("software").property("name","ripple").property("lang","java"). + addE("knows").from("marko").to("vadas"). + addE("knows").from("marko").to("josh") + """ + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).property(Cardinality.list, "friends", __.out("knows").values("name")) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 2 for count of "g.V(vid1).properties(\"friends\")" + + Scenario: g_VXvid1X_propertyXset_langs_outXcreatedX_valuesXlangXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29). + addV("person").property("name","vadas").property("age",27). + addV("software").property("name","lop").property("lang","java").as("lop"). + addV("person").property("name","josh").property("age",32).as("josh"). + addV("person").property("name","peter").property("age",35). + addV("software").property("name","ripple").property("lang","java").as("ripple"). + addE("created").from("josh").to("lop"). + addE("created").from("josh").to("ripple") + """ + And using the parameter vid1 defined as "v[josh].id" + And the traversal of + """ + g.V(vid1).property(Cardinality.set, "langs", __.out("created").values("lang")) + """ + When iterated to list + Then the result should have a count of 1 + And the graph should return 1 for count of "g.V(vid1).properties(\"langs\")" + + Scenario: g_VXvid1X_propertyXsingle_friend_outXknowsX_valuesXnameXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29).as("marko"). + addV("person").property("name","vadas").property("age",27).as("vadas"). + addV("software").property("name","lop").property("lang","java"). + addV("person").property("name","josh").property("age",32).as("josh"). + addV("person").property("name","peter").property("age",35). + addV("software").property("name","ripple").property("lang","java"). + addE("knows").from("marko").to("vadas"). + addE("knows").from("marko").to("josh") + """ + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).property(Cardinality.single, "friend", __.out("knows").values("name")) + """ + When iterated to list + Then the traversal will raise an error + + @GraphComputerVerificationMidVNotSupported + Scenario: g_VXvid1X_propertyXVXvid1X_groupX_byXidX_byXvaluesXnameXXX + Given the empty graph + And the graph initializer of + """ + g.addV("person").property("name","marko").property("age",29) + """ + And using the parameter vid1 defined as "v[marko].id" + And the traversal of + """ + g.V(vid1).property(__.V(vid1).group().by(__.id()).by(__.values("name"))) + """ + When iterated to list + Then the traversal will raise an error diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java index a950daeefed..fc7c64b0609 100644 --- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java +++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java @@ -59,6 +59,14 @@ public TinkerGraphStep(final GraphStepContract originalGraphStep) { super(originalGraphStep.getTraversal(), originalGraphStep.getReturnClass(), originalGraphStep.isStartStep(), originalGraphStep.getIds()); originalGraphStep.getLabels().forEach(this::addLabel); + // preserve the idTraversal if the original GraphStep had one + if (originalGraphStep instanceof GraphStep) { + final GraphStep gs = (GraphStep) originalGraphStep; + if (gs.getIdTraversal() != null) { + this.setIdTraversal(gs.getIdTraversal()); + } + } + // we used to only setIteratorSupplier() if there were no ids OR the first id was instanceof Element, // but that allowed the filter in g.V(v).has('k','v') to be ignored. this created problems for // PartitionStrategy which wants to prevent someone from passing "v" from one TraversalSource to diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategy.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategy.java index c9e19593a77..947cdcefa38 100644 --- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategy.java +++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategy.java @@ -54,8 +54,18 @@ public void apply(final Traversal.Admin traversal) { Step currentStep = tinkerGraphStep.getNextStep(); while (currentStep instanceof HasStep || currentStep instanceof NoOpBarrierStep) { if (currentStep instanceof HasStep) { - List hasContainers = ((HasContainerHolder) currentStep).getHasContainers(); - for (HasContainer hasContainer : hasContainers) { + final List hasContainers = ((HasContainerHolder) currentStep).getHasContainers(); + + // skip folding this HasStep if any HasContainer holds a child traversal - + // its value is dynamic (resolved per-traverser) and cannot be pushed into + // TinkerGraphStep. Continue to the next step so that subsequent literal + // HasSteps can still be folded. + if (hasContainers.stream().anyMatch(HasContainer::hasTraversal)) { + currentStep = currentStep.getNextStep(); + continue; + } + + for (final HasContainer hasContainer : hasContainers) { if (!GraphStep.processHasContainerIds(tinkerGraphStep, hasContainer)) tinkerGraphStep.addHasContainer(hasContainer); } diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTraversalTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTraversalTest.java new file mode 100644 index 00000000000..c17de52f53e --- /dev/null +++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTraversalTest.java @@ -0,0 +1,205 @@ +/* + * 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. + */ +package org.apache.tinkerpop.gremlin.tinkergraph.process.traversal.strategy.optimization; + +import org.apache.tinkerpop.gremlin.process.traversal.Step; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer; +import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.tinkergraph.process.traversal.step.sideEffect.TinkerGraphStep; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasSize; + +/** + * Property 9: Traversal-bearing HasContainers are not folded into GraphStep. + *

+ * For any traversal of the form {@code g.V().has(key, traversal)} or {@code g.V().has(key, P.eq(traversal))}, + * after applying {@link TinkerGraphStepStrategy}, the {@link HasStep} SHALL remain as a separate step in the + * traversal plan and SHALL NOT be folded into the {@link TinkerGraphStep}. + *

+ * Validates: Requirements 8.1, 8.2, 8.3 + */ +public class TinkerGraphStepStrategyTraversalTest { + + private Graph graph; + private GraphTraversalSource g; + + @Before + public void setup() { + graph = TinkerGraph.open(); + g = graph.traversal(); + } + + @After + public void teardown() throws Exception { + graph.close(); + } + + /** + * Applies TinkerGraphStepStrategy to the given traversal and returns the step list. + */ + private List applyStrategy(final Traversal.Admin traversal) { + final TraversalStrategies strategies = new DefaultTraversalStrategies(); + strategies.addStrategies(TinkerGraphStepStrategy.instance()); + traversal.setStrategies(strategies); + traversal.applyStrategies(); + return traversal.getSteps(); + } + + @Test + public void shouldNotFoldTraversalBearingHasContainerIntoGraphStep() { + // g.V().has("name", __.constant("marko")) - traversal-bearing HasContainer + final GraphTraversal traversal = g.V().has("name", __.constant("marko")); + final List steps = applyStrategy(traversal.asAdmin()); + + // The traversal plan should contain at least 2 steps: + // TinkerGraphStep (replacing GraphStep) and HasStep (not folded) + assertThat(steps, hasSize(greaterThanOrEqualTo(2))); + assertThat(steps.get(0), instanceOf(TinkerGraphStep.class)); + + // The HasStep should remain as a separate step + final boolean hasStepPresent = steps.stream().anyMatch(s -> s instanceof HasStep); + assertThat("HasStep with traversal-bearing HasContainer should NOT be folded into TinkerGraphStep", + hasStepPresent, is(true)); + + // The TinkerGraphStep should have no folded HasContainers + final TinkerGraphStep tinkerGraphStep = (TinkerGraphStep) steps.get(0); + assertThat("TinkerGraphStep should have no folded HasContainers for traversal-bearing has()", + tinkerGraphStep.getHasContainers(), hasSize(0)); + } + + @Test + public void shouldStillFoldLiteralHasContainerIntoGraphStep() { + // g.V().has("name", "marko") - literal HasContainer should still be folded + final GraphTraversal traversal = g.V().has("name", "marko"); + final List steps = applyStrategy(traversal.asAdmin()); + + // After folding, the HasStep should be absorbed into TinkerGraphStep + assertThat(steps, hasSize(1)); + assertThat(steps.get(0), instanceOf(TinkerGraphStep.class)); + + // The TinkerGraphStep should have the folded HasContainer + final TinkerGraphStep tinkerGraphStep = (TinkerGraphStep) steps.get(0); + assertThat(tinkerGraphStep.getHasContainers(), hasSize(1)); + } + + @Test + public void shouldNotFoldPredicateWithTraversalIntoGraphStep() { + // g.V().has("name", P.eq(__.constant("marko"))) - predicate with traversal + final GraphTraversal traversal = + g.V().has("name", org.apache.tinkerpop.gremlin.process.traversal.P.eq(__.constant("marko"))); + final List steps = applyStrategy(traversal.asAdmin()); + + // The HasStep should remain as a separate step + assertThat(steps, hasSize(greaterThanOrEqualTo(2))); + assertThat(steps.get(0), instanceOf(TinkerGraphStep.class)); + + final boolean hasStepPresent = steps.stream().anyMatch(s -> s instanceof HasStep); + assertThat("HasStep with P.eq(traversal) should NOT be folded into TinkerGraphStep", + hasStepPresent, is(true)); + } + + @Test + public void shouldFoldLiteralHasButNotTraversalHasInMixedTraversal() { + // g.V().has("name", "marko").has("age", __.constant(29)) + // Both containers end up in the same HasStep (TraversalHelper.addHasContainer merges). + // The strategy skips the entire HasStep because it contains a traversal-bearing container. + final GraphTraversal traversal = + g.V().has("name", "marko").has("age", __.constant(29)); + final List steps = applyStrategy(traversal.asAdmin()); + + // TinkerGraphStep should have NO folded HasContainers (the merged HasStep is skipped) + assertThat(steps.get(0), instanceOf(TinkerGraphStep.class)); + final TinkerGraphStep tinkerGraphStep = (TinkerGraphStep) steps.get(0); + + // The HasStep with both containers should remain as a separate step + final boolean hasStepPresent = steps.stream().anyMatch(s -> s instanceof HasStep); + assertThat("HasStep with mixed containers should remain as separate step", + hasStepPresent, is(true)); + } + + @Test + public void shouldFoldLiteralHasAfterBarrierAndTraversalHas() { + // g.V().has("age", __.constant(29)).barrier().has("name", "marko") + // The barrier separates the two HasSteps. The strategy should: + // - Skip the traversal-bearing HasStep (has("age", traversal)) + // - Stop at the barrier (not a HasStep or NoOpBarrierStep... actually NoOpBarrierStep IS handled) + // Let's use a different separator. Actually NoOpBarrierStep is handled by the while loop. + // The key test is: after skipping a traversal-bearing HasStep, the strategy continues + // and can fold subsequent literal HasSteps. + // + // With separate HasSteps (not merged), the strategy should fold the literal one. + // We can force separate HasSteps by inserting a NoOpBarrierStep between them. + final GraphTraversal traversal = + g.V().has("age", __.constant(29)).barrier().has("name", "marko"); + final List steps = applyStrategy(traversal.asAdmin()); + + // TinkerGraphStep should have the literal "name" HasContainer folded + assertThat(steps.get(0), instanceOf(TinkerGraphStep.class)); + final TinkerGraphStep tinkerGraphStep = (TinkerGraphStep) steps.get(0); + assertThat("Literal HasContainer after barrier should be folded even when preceded by traversal-bearing HasStep", + tinkerGraphStep.getHasContainers(), hasSize(1)); + assertThat(tinkerGraphStep.getHasContainers().get(0).getKey(), is("name")); + + // The traversal-bearing HasStep for "age" should remain + final boolean hasStepPresent = steps.stream().anyMatch(s -> s instanceof HasStep); + assertThat("Traversal-bearing HasStep should remain as separate step", + hasStepPresent, is(true)); + } + + @Test + public void shouldFoldMultipleLiteralHasStepsSeparatedByTraversalHas() { + // g.V().has("name", "marko").has("age", __.constant(29)).barrier().has("lang", "java") + // has("name") is a separate literal HasStep, has("age") is a separate traversal HasStep, + // has("lang") is a separate literal HasStep after the barrier. + // Strategy should fold both literal HasSteps and skip the traversal one. + final GraphTraversal traversal = + g.V().has("name", "marko").has("age", __.constant(29)).barrier().has("lang", "java"); + final List steps = applyStrategy(traversal.asAdmin()); + + // TinkerGraphStep should have both literal HasContainers folded ("name" and "lang") + assertThat(steps.get(0), instanceOf(TinkerGraphStep.class)); + final TinkerGraphStep tinkerGraphStep = (TinkerGraphStep) steps.get(0); + assertThat("Both literal HasContainers should be folded", + tinkerGraphStep.getHasContainers(), hasSize(2)); + + // The traversal-bearing HasStep (age) should remain + final boolean hasStepPresent = steps.stream().anyMatch(s -> s instanceof HasStep); + assertThat("Traversal-bearing HasStep should remain as separate step", + hasStepPresent, is(true)); + } + +}