You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2021/12/03 22:48:02 UTC
[tinkerpop] 01/01: TINKERPOP-2635 filtering for unproductive by() WIP
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2635
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 02533bc9a6a5a62bf043fd352bf24cfdabf8abed
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Dec 3 17:01:35 2021 -0500
TINKERPOP-2635 filtering for unproductive by() WIP
---
CHANGELOG.asciidoc | 2 +
docs/src/dev/developer/for-committers.asciidoc | 3 +
.../tinkerpop/gremlin/process/traversal/Path.java | 6 +-
.../tinkerpop/gremlin/process/traversal/Step.java | 2 +-
.../process/traversal/TraversalStrategies.java | 2 -
.../traversal/step/filter/DedupGlobalStep.java | 72 ++++++-----
.../traversal/step/filter/PathFilterStep.java | 17 ++-
.../traversal/step/filter/SampleGlobalStep.java | 20 +++-
.../traversal/step/filter/WherePredicateStep.java | 34 ++++--
.../process/traversal/step/map/GroupCountStep.java | 2 +-
.../process/traversal/step/map/GroupStep.java | 14 ++-
.../process/traversal/step/map/MathStep.java | 29 +++--
.../traversal/step/map/OrderGlobalStep.java | 15 ++-
.../process/traversal/step/map/OrderLocalStep.java | 104 ++++++++++------
.../process/traversal/step/map/PathStep.java | 44 ++++---
.../process/traversal/step/map/ProjectStep.java | 2 +-
.../traversal/step/map/PropertyMapStep.java | 13 +-
.../process/traversal/step/map/SelectOneStep.java | 7 +-
.../process/traversal/step/map/SelectStep.java | 12 +-
.../process/traversal/step/map/TreeStep.java | 12 +-
.../step/sideEffect/AggregateGlobalStep.java | 8 +-
.../step/sideEffect/AggregateLocalStep.java | 2 +-
.../traversal/step/sideEffect/SackValueStep.java | 18 ++-
.../process/traversal/util/TraversalProduct.java | 55 +++++++++
.../process/traversal/util/TraversalUtil.java | 133 +++++++++++++--------
.../gremlin/util/function/ChainedComparator.java | 2 +
.../gremlin/process/traversal/PathTest.java | 20 ++++
.../optimization/PathProcessorStrategyTest.java | 19 +--
.../Gherkin/GherkinTestRunner.cs | 3 +-
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 43 +++++++
.../test/cucumber/feature-steps.js | 2 +-
.../gremlin-javascript/test/cucumber/gremlin.js | 45 ++++++-
gremlin-python/src/main/python/radish/gremlin.py | 45 +++++++
.../server/op/session/SessionOpProcessor.java | 6 +-
gremlin-test/features/filter/CyclicPath.feature | 14 +++
gremlin-test/features/filter/Dedup.feature | 48 +++++++-
gremlin-test/features/filter/Sample.feature | 11 ++
gremlin-test/features/filter/SimplePath.feature | 17 +++
gremlin-test/features/filter/Where.feature | 13 +-
gremlin-test/features/map/Math.feature | 28 +++++
gremlin-test/features/map/Max.feature | 40 +++++++
gremlin-test/features/map/Mean.feature | 44 +++++++
gremlin-test/features/map/Min.feature | 40 +++++++
gremlin-test/features/map/Order.feature | 76 +++++++++++-
gremlin-test/features/map/Path.feature | 14 +++
gremlin-test/features/map/Project.feature | 18 +++
gremlin-test/features/map/Select.feature | 31 ++++-
gremlin-test/features/map/Sum.feature | 45 ++++++-
gremlin-test/features/map/ValueMap.feature | 18 ++-
gremlin-test/features/sideEffect/Aggregate.feature | 73 ++++++++++-
gremlin-test/features/sideEffect/Group.feature | 22 ++++
.../features/sideEffect/GroupCount.feature | 22 ++++
gremlin-test/features/sideEffect/Sack.feature | 14 +++
.../process/traversal/step/filter/DedupTest.java | 3 +-
.../process/traversal/step/filter/WhereTest.java | 4 +-
.../process/traversal/step/map/MaxTest.java | 2 -
.../process/traversal/step/map/MeanTest.java | 2 -
.../process/traversal/step/map/MinTest.java | 2 -
.../process/traversal/step/map/OrderTest.java | 2 +-
.../process/traversal/step/map/PathTest.java | 4 +-
.../process/traversal/step/map/ProjectTest.java | 37 ++++--
.../process/traversal/step/map/SelectTest.java | 2 +-
.../process/traversal/step/map/SumTest.java | 4 +-
.../traversal/step/sideEffect/AggregateTest.java | 4 +-
.../traversal/step/sideEffect/GroupTest.java | 2 +-
.../traversal/step/sideEffect/TreeTest.java | 25 ++++
66 files changed, 1253 insertions(+), 241 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 703ba95..08275c2 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -39,6 +39,8 @@ limitations under the License.
* Created a way to produce a corpus of Gremlin traversals via `FeatureReader` and `DocumentationReader` in `gremlin-language`.
* Exposed Gherkin tests as part of the provider test suite.
* Packaged Gherkin tests and data as standalone package as a convenience distribution.
+* Removed `ProductiveByStrategy` as a strategy that is applied by default.
+* Changed `by()` modulator semantics to consistently filter.
* Removed previously deprecated `application/vnd.gremlin-v1.0+gryo-lite` serialization format.
* Removed previously deprecated `AuthenticationSettings.enableAuditLog`.
* Removed previously deprecated `GroovyTranslator` from `gremlin-groovy` module.
diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index 4114259..8a6c568 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -530,6 +530,9 @@ or meta-properties for creating or querying data.
* `@RemoteOnly` - The scenario uses some Gremlin syntax that cannot be supported outside of remote test executions. The
best example of this sort of test would be one that uses the remote `Lambda` syntax.
+Tag filters can be applied to Intellij at execution time by adding a system properties of
+`-Dcucumber.filter.tags=<step-filter>`.
+
== Developing Benchmarks
Benchmarks are a useful tool to track performance between TinkerPop versions and also as tools to aid development
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
index d8e51c2..9d78f21 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
@@ -198,8 +199,7 @@ public interface Path extends Cloneable, Iterable<Object> {
public Path clone();
/**
- * Determines whether the path is a simple or not.
- * A simple path has no cycles and thus, no repeated objects.
+ * Determines whether the path is a simple or not. A simple path has no cycles and thus, no repeated objects.
*
* @return Whether the path is simple or not
*/
@@ -207,7 +207,7 @@ public interface Path extends Cloneable, Iterable<Object> {
final List<Object> objects = this.objects();
for (int i = 0; i < objects.size() - 1; i++) {
for (int j = i + 1; j < objects.size(); j++) {
- if (objects.get(i).equals(objects.get(j)))
+ if (Objects.equals(objects.get(i), objects.get(j)))
return false;
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java
index 6bc34f5..99fdd91 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java
@@ -41,7 +41,7 @@ import java.util.Set;
public interface Step<S, E> extends Iterator<Traverser.Admin<E>>, Serializable, Cloneable {
/**
- * Add a iterator of {@link Traverser.Admin} objects of type S to the step.
+ * Add an iterator of {@link Traverser.Admin} objects of type S to the step.
*
* @param starts The iterator of objects to add
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index 37ad108..01deea1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -23,7 +23,6 @@ import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.finaliza
import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy;
import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.MessagePassingReductionStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
@@ -225,7 +224,6 @@ public interface TraversalStrategies extends Serializable, Cloneable, Iterable<T
IncidentToAdjacentStrategy.instance(),
AdjacentToIncidentStrategy.instance(),
ByModulatorOptimizationStrategy.instance(),
- ProductiveByStrategy.instance(),
FilterRankingStrategy.instance(),
MatchPredicateStrategy.instance(),
RepeatUnrollStrategy.instance(),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
index dd8235d..9f5b0e5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
@@ -31,6 +31,7 @@ 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.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -73,11 +74,18 @@ public final class DedupGlobalStep<S> extends FilterStep<S> implements Traversal
if (this.onGraphComputer && !this.executingAtMaster) return true;
traverser.setBulk(1L);
if (null == this.dedupLabels) {
- return this.duplicateSet.add(TraversalUtil.applyNullable(traverser, this.dedupTraversal));
+ final TraversalProduct product = TraversalUtil.produce(traverser, this.dedupTraversal);
+ return product.isProductive() && this.duplicateSet.add(product.get());
} else {
final List<Object> objects = new ArrayList<>(this.dedupLabels.size());
- this.dedupLabels.forEach(label -> objects.add(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal)));
- return this.duplicateSet.add(objects);
+ for (String label : dedupLabels) {
+ final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal);
+ if (!product.isProductive()) break;
+ objects.add(product.get());
+ }
+
+ // the object sizes must be equal or else it means a by() wasn't productive and that path will be filtered
+ return objects.size() == dedupLabels.size() && duplicateSet.add(objects);
}
}
@@ -194,42 +202,50 @@ public final class DedupGlobalStep<S> extends FilterStep<S> implements Traversal
while (this.starts.hasNext()) {
final Traverser.Admin<S> traverser = this.starts.next();
final Object object;
+ boolean productive;
if (null != this.dedupLabels) {
object = new ArrayList<>(this.dedupLabels.size());
for (final String label : this.dedupLabels) {
- ((List) object).add(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal));
+ final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal);
+ if (!product.isProductive()) break;
+ ((List) object).add(product.get());
}
+
+ productive = ((List) object).size() == this.dedupLabels.size();
} else {
- object = TraversalUtil.applyNullable(traverser, this.dedupTraversal);
+ final TraversalProduct product = TraversalUtil.produce(traverser, this.dedupTraversal);
+ productive = product.isProductive();
+ object = productive ? product.get() : null;
}
- if (!map.containsKey(object)) {
- traverser.setBulk(1L);
-
- // DetachedProperty and DetachedVertexProperty both have a transient for the Host element. that causes
- // trouble for olap which ends up requiring the Host later. can't change the transient without some
- // consequences: (1) we break gryo formatting and io tests start failing (2) storing the element with
- // the property has the potential to bloat detached Element instances as it basically stores that data
- // twice. Not sure if it's smart to change that at least in 3.4.x and not without some considerable
- // thought as to what might be major changes. To work around the problem we will detach properties as
- // references so that the parent element goes with it. Also, given TINKERPOP-2318 property comparisons
- // have changed in such a way that allows this to work properly
- if (this.onGraphComputer) {
- if (traverser.get() instanceof Property)
- traverser.set(ReferenceFactory.detach(traverser.get()));
- else
- traverser.set(DetachedFactory.detach(traverser.get(), true));
- } else {
- traverser.set(traverser.get());
+
+ if (productive) {
+ if (!map.containsKey(object)) {
+ traverser.setBulk(1L);
+
+ // DetachedProperty and DetachedVertexProperty both have a transient for the Host element. that causes
+ // trouble for olap which ends up requiring the Host later. can't change the transient without some
+ // consequences: (1) we break gryo formatting and io tests start failing (2) storing the element with
+ // the property has the potential to bloat detached Element instances as it basically stores that data
+ // twice. Not sure if it's smart to change that at least in 3.4.x and not without some considerable
+ // thought as to what might be major changes. To work around the problem we will detach properties as
+ // references so that the parent element goes with it. Also, given TINKERPOP-2318 property comparisons
+ // have changed in such a way that allows this to work properly
+ if (this.onGraphComputer) {
+ if (traverser.get() instanceof Property)
+ traverser.set(ReferenceFactory.detach(traverser.get()));
+ else
+ traverser.set(DetachedFactory.detach(traverser.get(), true));
+ } else {
+ traverser.set(traverser.get());
+ }
+ map.put(object, traverser);
}
- map.put(object, traverser);
}
}
+
this.barrier = null;
this.barrierIterator = null;
- if (map.isEmpty())
- throw FastNoSuchElementException.instance();
- else
- return map;
+ return map;
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
index 8fa93bf..7a7d9db 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -62,8 +63,20 @@ public final class PathFilterStep<S> extends FilterStep<S> implements FromToModu
else {
this.traversalRing.reset();
final Path byPath = MutablePath.make();
- path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels));
- return byPath.isSimple() == this.isSimple;
+ final List<Set<String>> labels = path.labels();
+ final List<Object> objects = path.objects();
+ for (int ix = 0; ix < objects.size(); ix++) {
+ final Traversal.Admin t = traversalRing.next();
+ final TraversalProduct p = TraversalUtil.produce(objects.get(ix), t);
+
+ // if not productive we can quit coz this path is getting filtered
+ if (!p.isProductive()) break;
+
+ byPath.extend(p.get(), labels.get(ix));
+ }
+
+ // the path sizes must be equal or else it means a by() wasn't productive and that path will be filtered
+ return path.size() == byPath.size() && byPath.isSimple() == this.isSimple;
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
index b342100..20c8396a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
@@ -28,11 +28,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrie
import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import java.util.Random;
import java.util.Set;
@@ -79,7 +81,7 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
@Override
public void processAllStarts() {
while (this.starts.hasNext()) {
- this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
+ this.createProjectedTraverser(this.starts.next()).ifPresent(traverserSet::add);
}
}
@@ -124,8 +126,20 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
}
- private final ProjectedTraverser<S, Number> createProjectedTraverser(final Traverser.Admin<S> traverser) {
- return new ProjectedTraverser<>(traverser, Collections.singletonList(TraversalUtil.apply(traverser, this.probabilityTraversal)));
+ private Optional<ProjectedTraverser<S, Number>> createProjectedTraverser(final Traverser.Admin<S> traverser) {
+ final TraversalProduct product = TraversalUtil.produce(traverser, this.probabilityTraversal);
+ if (product.isProductive()) {
+ final Object o = product.get();
+ if (!(o instanceof Number)) {
+ throw new IllegalStateException(String.format(
+ "Traverser %s does not evaluate to a number with %s", traverser, this.probabilityTraversal));
+ }
+
+ return Optional.of(new ProjectedTraverser<>(traverser, Collections.singletonList((Number) product.get())));
+ } else {
+ return Optional.empty();
+ }
+
}
@Override
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 2ab3d9d..6820f88 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
@@ -28,6 +28,7 @@ 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;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -74,11 +75,21 @@ public final class WherePredicateStep<S> extends FilterStep<S> implements Scopin
}
}
- private void setPredicateValues(final P<Object> predicate, final Traverser.Admin<S> traverser, final Iterator<String> selectKeysIterator) {
- if (predicate instanceof ConnectiveP)
- ((ConnectiveP<Object>) predicate).getPredicates().forEach(p -> this.setPredicateValues(p, traverser, selectKeysIterator));
- else
- predicate.setValue(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, selectKeysIterator.next(), traverser), this.traversalRing.next()));
+ private boolean setPredicateValues(final P<Object> predicate, final Traverser.Admin<S> traverser, final Iterator<String> selectKeysIterator) {
+ if (predicate instanceof ConnectiveP) {
+ for (P<Object> p : ((ConnectiveP<Object>) predicate).getPredicates()) {
+ if (!this.setPredicateValues(p, traverser, selectKeysIterator))
+ return false;
+ }
+
+ return true;
+ } else {
+ final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, selectKeysIterator.next(), traverser), this.traversalRing.next());
+ if (product.isProductive())
+ predicate.setValue(product.get());
+
+ return product.isProductive();
+ }
}
public Optional<P<?>> getPredicate() {
@@ -101,17 +112,18 @@ public final class WherePredicateStep<S> extends FilterStep<S> implements Scopin
@Override
protected boolean filter(final Traverser.Admin<S> traverser) {
- final Object value = null == this.startKey ?
- TraversalUtil.applyNullable(traverser, this.traversalRing.next()) :
- TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, this.startKey, traverser), this.traversalRing.next());
- this.setPredicateValues(this.predicate, traverser, this.selectKeys.iterator());
+ 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();
- return this.predicate.test(value);
+
+ return product.isProductive() && predicateValuesProductive && this.predicate.test(product.get());
}
@Override
public String toString() {
- // TODO: revert the predicates to their string form?
return StringFactory.stepString(this, this.startKey, this.predicate, this.traversalRing);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
index 0f3fa25..77fd379 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
@@ -54,7 +54,7 @@ public class GroupCountStep<S, E> extends ReducingBarrierStep<S, Map<E, Long>> i
@Override
public Map<E, Long> projectTraverser(final Traverser.Admin<S> traverser) {
final Map<E, Long> map = new HashMap<>(1);
- map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), traverser.bulk());
+ TraversalUtil.produce(traverser, this.keyTraversal).ifProductive(p -> map.put((E) p, traverser.bulk()));
return map;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
index 2213b2e..ff7ba1c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
@@ -124,11 +124,15 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
resetBarrierForProfiling = false;
}
- if (null == this.barrierStep) {
- if (this.valueTraversal.hasNext())
- map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.valueTraversal.next());
- } else if (this.barrierStep.hasNextBarrier())
- map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.barrierStep.nextBarrier());
+ TraversalUtil.produce(traverser, this.keyTraversal).ifProductive(p -> {
+ if (null == this.barrierStep) {
+ if (this.valueTraversal.hasNext()) {
+ map.put((K) p, (V) this.valueTraversal.next());
+ }
+ } else if (this.barrierStep.hasNextBarrier())
+ map.put((K) p, (V) this.barrierStep.nextBarrier());
+ });
+
return map;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
index 149f67a..612e20d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
@@ -29,6 +29,8 @@ 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.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -45,7 +47,7 @@ import java.util.regex.Pattern;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
-public final class MathStep<S> extends ScalarMapStep<S, Double> implements ByModulating, TraversalParent, Scoping, PathProcessor {
+public final class MathStep<S> extends MapStep<S, Double> implements ByModulating, TraversalParent, Scoping, PathProcessor {
private static final String CURRENT = "_";
private final String equation;
@@ -61,16 +63,21 @@ public final class MathStep<S> extends ScalarMapStep<S, Double> implements ByMod
@Override
protected Traverser.Admin<Double> processNextStart() {
- return PathProcessor.processTraverserPathLabels(super.processNextStart(), this.keepLabels);
- }
+ final Traverser.Admin traverser = this.starts.next();
- @Override
- protected Double map(final Traverser.Admin<S> traverser) {
final Expression localExpression = new Expression(this.expression.getExpression());
+ boolean productive = true;
for (final String var : this.expression.getVariables()) {
- final Object o = var.equals(CURRENT) ?
- TraversalUtil.applyNullable(traverser, this.traversalRing.next()) :
- TraversalUtil.applyNullable((S) this.getNullableScopeValue(Pop.last, var, traverser), this.traversalRing.next());
+ final TraversalProduct product = var.equals(CURRENT) ?
+ TraversalUtil.produce(traverser, this.traversalRing.next()) :
+ TraversalUtil.produce((S) this.getNullableScopeValue(Pop.last, var, traverser), this.traversalRing.next());
+
+ if (!product.isProductive()) {
+ productive = false;
+ break;
+ }
+
+ final Object o = product.get();
// it's possible for ElementValueTraversal to return null or something that is possibly not a Number.
// worth a check to try to return a nice error message. The TraversalRing<S, Number> is a bit optimistic
@@ -83,7 +90,11 @@ public final class MathStep<S> extends ScalarMapStep<S, Double> implements ByMod
localExpression.setVariable(var, ((Number) o).doubleValue());
}
this.traversalRing.reset();
- return localExpression.evaluate();
+
+ // if at least one of the traversals wasnt productive it will filter
+ return productive ?
+ PathProcessor.processTraverserPathLabels(traverser.split(localExpression.evaluate(), this), this.keepLabels) :
+ EmptyTraverser.instance();
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
index a7f7892..2723790 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrie
import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.apache.tinkerpop.gremlin.util.function.MultiComparator;
@@ -42,6 +43,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.BinaryOperator;
@@ -79,7 +81,8 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
@Override
public void processAllStarts() {
while (this.starts.hasNext()) {
- this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
+ // only add the traverser if the comparator traversal was productive
+ this.createProjectedTraverser(this.starts.next()).ifPresent(traverserSet::add);
}
}
@@ -170,16 +173,20 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.multiComparator, this.random), false, true);
}
- private final ProjectedTraverser<S, Object> createProjectedTraverser(final Traverser.Admin<S> traverser) {
+ private Optional<ProjectedTraverser<S, Object>> createProjectedTraverser(final Traverser.Admin<S> traverser) {
// this was ProjectedTraverser<S, C> but the projection may not be C in the case of a lambda where a
// Comparable may not be expected but rather an object that can be compared in any way given a lambda.
// not sure why this is suddenly an issue but Intellij would not let certain tests pass without this
// adjustment here.
final List<Object> projections = new ArrayList<>(this.comparators.size());
for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
- projections.add(TraversalUtil.apply(traverser, pair.getValue0()));
+ final TraversalProduct product = TraversalUtil.produce(traverser, pair.getValue0());
+ if (!product.isProductive()) break;
+ projections.add(product.get());
}
- return new ProjectedTraverser(traverser, projections);
+
+ // if a traversal wasn't productive then the sizes wont match and it will filter
+ return projections.size() == comparators.size() ? Optional.of(new ProjectedTraverser(traverser, projections)) : Optional.empty();
}
private final MultiComparator<C> createMultiComparator() {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
index eb3a5f8..fdcfaa4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
@@ -27,8 +27,9 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.ComparatorHolder;
import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
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.TraversalProduct;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.ChainedComparator;
import org.javatuples.Pair;
import java.util.ArrayList;
@@ -48,7 +49,6 @@ import java.util.stream.Collectors;
public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep<S, S> implements ComparatorHolder<S, C>, ByModulating, TraversalParent, Seedable {
private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
- private ChainedComparator<S, C> chainedComparator = null;
private final Random random = new Random();
public OrderLocalStep(final Traversal.Admin traversal) {
@@ -62,15 +62,73 @@ public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep
@Override
protected S map(final Traverser.Admin<S> traverser) {
- if (null == this.chainedComparator)
- this.chainedComparator = new ChainedComparator<>(false, this.comparators);
final S start = traverser.get();
- if (start instanceof Collection)
- return (S) sortCollection((Collection) start, this.chainedComparator);
- else if (start instanceof Map)
- return (S) sortMap((Map) start, this.chainedComparator);
- else
- return start;
+
+ // modulate each traverser object and keep its value to sort on as Pair<traverser-object,List<modulated-object>>
+ // as of 3.6.0 this transformation occurs in place and values held in memory so that unproductive by() values
+ // can be filtered. without this trade-off for more memory it would be necessary to apply the modulation twice
+ // once for the filter and once for the compare.
+ if (start instanceof Collection) {
+ final Collection<S> original = (Collection<S>) start;
+ final List<Pair<S, List<C>>> filteredAndModulated = filterAndModulate(original);
+ return (S) filteredAndModulated.stream().map(Pair::getValue0).collect(Collectors.toList());
+ } else if (start instanceof Map) {
+ final List<Pair<S, List<C>>> filteredAndModulated = filterAndModulate(((Map) start).entrySet());
+ final LinkedHashMap sortedMap = new LinkedHashMap();
+ filteredAndModulated.stream().map(Pair::getValue0).map(entry -> (Map.Entry) entry).
+ forEach(entry -> sortedMap.put(entry.getKey(), entry.getValue()));
+ return (S) sortedMap;
+ }
+
+ return start;
+ }
+
+ /**
+ * Take the collection and apply modulators removing traversers that have modulators that aren't productive.
+ */
+ private List<Pair<S, List<C>>> filterAndModulate(final Collection<S> original) {
+ if (comparators.isEmpty())
+ this.comparators.add(new Pair<>(new IdentityTraversal(), (Comparator) Order.asc));
+
+ // detect shuffle and optimize by either ignoring other comparators if shuffle is last or
+ // ignoring comparators that are shuffles if they are in the middle
+ final boolean isShuffle = (Comparator) this.comparators.get(this.comparators.size() - 1).getValue1() == Order.shuffle;
+ final List<Pair<Traversal.Admin<S, C>, Comparator<C>>> relevantComparators = isShuffle ?
+ this.comparators :
+ this.comparators.stream().filter(p -> (Comparator) p.getValue1() != Order.shuffle).collect(Collectors.toList());
+
+ final List<Pair<S, List<C>>> filteredAndModulated = new ArrayList<>();
+ final List<Traversal.Admin<S, C>> modulators = relevantComparators.stream().map(Pair::getValue0).collect(Collectors.toList());
+ for (S s : original) {
+ // filter out unproductive by()
+ final List<C> modulations = modulators.stream().map(t -> TraversalUtil.produce(s, t)).
+ filter(TraversalProduct::isProductive).
+ map(product -> (C) product.get()).collect(Collectors.toList());
+
+ // when sizes arent the same it means a by() wasn't productive and it is ignored
+ if (modulations.size() == modulators.size()) {
+ filteredAndModulated.add(Pair.with(s, modulations));
+ }
+ }
+
+ if (isShuffle) {
+ Collections.shuffle(filteredAndModulated, random);
+ } else {
+ // sort the filter/modulated local list in place using the index of the modulator/comparators
+ Collections.sort(filteredAndModulated, (o1, o2) -> {
+ final List<C> modulated1 = o1.getValue1();
+ final List<C> modulated2 = o2.getValue1();
+ for (int ix = 0; ix < modulated1.size(); ix++) {
+ final int comparison = relevantComparators.get(ix).getValue1().compare(modulated1.get(ix), modulated2.get(ix));
+ if (comparison != 0)
+ return comparison;
+ }
+
+ return 0;
+ });
+ }
+
+ return filteredAndModulated;
}
@Override
@@ -138,7 +196,6 @@ public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep
for (final Pair<Traversal.Admin<S, C>, Comparator<C>> comparator : this.comparators) {
clone.comparators.add(new Pair<>(comparator.getValue0().clone(), comparator.getValue1()));
}
- clone.chainedComparator = null;
return clone;
}
@@ -147,29 +204,4 @@ public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep
super.setTraversal(parentTraversal);
this.comparators.stream().map(Pair::getValue0).forEach(TraversalParent.super::integrateChild);
}
-
- /////////////
-
- private <A> List<A> sortCollection(final Collection<A> collection, final ChainedComparator comparator) {
- if (collection instanceof List) {
- if (comparator.isShuffle())
- Collections.shuffle((List) collection, random);
- else
- Collections.sort((List) collection, comparator);
- return (List<A>) collection;
- } else {
- return sortCollection(new ArrayList<>(collection), comparator);
- }
- }
-
- private <K, V> Map<K, V> sortMap(final Map<K, V> map, final ChainedComparator comparator) {
- final List<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
- if (comparator.isShuffle())
- Collections.shuffle(entries, random);
- else
- Collections.sort(entries, comparator);
- final LinkedHashMap<K, V> sortedMap = new LinkedHashMap<>();
- entries.forEach(entry -> sortedMap.put(entry.getKey(), entry.getValue()));
- return sortedMap;
- }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
index 07c8d7d..8d073a9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
@@ -27,6 +27,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -38,7 +40,7 @@ import java.util.Set;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
-public final class PathStep<S> extends ScalarMapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating, FromToModulating {
+public final class PathStep<S> extends MapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating, FromToModulating {
private TraversalRing<Object, Object> traversalRing;
private Set<String> keepLabels;
@@ -51,20 +53,6 @@ public final class PathStep<S> extends ScalarMapStep<S, Path> implements Travers
}
@Override
- protected Path map(final Traverser.Admin<S> traverser) {
- final Path path = traverser.path().subPath(this.fromLabel, this.toLabel);
- if (this.traversalRing.isEmpty())
- return path;
- else {
- this.traversalRing.reset();
- final Path byPath = MutablePath.make();
- path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels));
- return byPath;
- }
- }
-
-
- @Override
public PathStep<S> clone() {
final PathStep<S> clone = (PathStep<S>) super.clone();
clone.traversalRing = this.traversalRing.clone();
@@ -122,7 +110,31 @@ public final class PathStep<S> extends ScalarMapStep<S, Path> implements Travers
@Override
protected Traverser.Admin<Path> processNextStart() {
- return PathProcessor.processTraverserPathLabels(super.processNextStart(), this.keepLabels);
+ final Traverser.Admin<S> traverser = this.starts.next();
+ final Path path = traverser.path().subPath(this.fromLabel, this.toLabel);
+ if (this.traversalRing.isEmpty())
+ return PathProcessor.processTraverserPathLabels(traverser.split(path, this), this.keepLabels);
+ else {
+ this.traversalRing.reset();
+ final Path byPath = MutablePath.make();
+
+ final List<Set<String>> labels = path.labels();
+ final List<Object> objects = path.objects();
+ for (int ix = 0; ix < objects.size(); ix++) {
+ final Traversal.Admin t = traversalRing.next();
+ final TraversalProduct p = TraversalUtil.produce(objects.get(ix), t);
+
+ // if not productive we can quit coz this path is getting filtered
+ if (!p.isProductive()) break;
+
+ byPath.extend(p.get(), labels.get(ix));
+ }
+
+ // the path sizes must be equal or else it means a by() wasn't productive and that path will be filtered
+ return path.size() == byPath.size() ?
+ PathProcessor.processTraverserPathLabels(traverser.split(byPath, this), this.keepLabels) :
+ EmptyTraverser.instance();
+ }
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
index b97c8d6..1aa9eae 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
@@ -52,7 +52,7 @@ public final class ProjectStep<S, E> extends ScalarMapStep<S, Map<String, E>> im
protected Map<String, E> map(final Traverser.Admin<S> traverser) {
final Map<String, E> end = new LinkedHashMap<>(this.projectKeys.size(), 1.0f);
for (final String projectKey : this.projectKeys) {
- end.put(projectKey, TraversalUtil.applyNullable(traverser, this.traversalRing.next()));
+ TraversalUtil.produce(traverser, this.traversalRing.next()).ifProductive(p -> end.put(projectKey, (E) p));
}
this.traversalRing.reset();
return end;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
index 12cd6be..35f83cd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.Element;
@@ -39,6 +40,7 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -108,8 +110,15 @@ public class PropertyMapStep<K,E> extends ScalarMapStep<Element, Map<K, E>>
}
}
if (!traversalRing.isEmpty()) {
- for (final Object key : map.keySet()) {
- map.compute(key, (k, v) -> TraversalUtil.applyNullable(v, (Traversal.Admin) this.traversalRing.next()));
+ // will cop a ConcurrentModification if a key is dropped so need this little copy here
+ final Set<Object> keys = new HashSet<>(map.keySet());
+ for (final Object key : keys) {
+ map.compute(key, (k, v) -> {
+ final TraversalProduct product = TraversalUtil.produce(v, (Traversal.Admin) this.traversalRing.next());
+
+ // compute() should take the null and remove the key
+ return product.isProductive() ? product.get() : null;
+ });
}
this.traversalRing.reset();
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
index 976c512..b2de4b0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
@@ -27,6 +27,7 @@ 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.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -59,7 +60,11 @@ public final class SelectOneStep<S, E> extends MapStep<S, E> implements Traversa
try {
final S o = getScopeValue(pop, selectKey, traverser);
if (null == o) return traverser.split(null, this);
- final Traverser.Admin<E> outTraverser = traverser.split(TraversalUtil.applyNullable(o, this.selectTraversal), this);
+
+ final TraversalProduct product = TraversalUtil.produce(o, this.selectTraversal);
+ if (!product.isProductive()) return EmptyTraverser.instance();
+
+ final Traverser.Admin<E> outTraverser = traverser.split((E) product.get(), this);
if (!(this.getTraversal().getParent() instanceof MatchStep))
PathProcessor.processTraverserPathLabels(outTraverser, this.keepLabels);
return outTraverser;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
index 9edde9d..05a6a5b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
@@ -27,6 +27,7 @@ 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.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -69,8 +70,17 @@ public final class SelectStep<S, E> extends MapStep<S, Map<String, E>> implement
try {
for (final String selectKey : this.selectKeys) {
final E end = this.getScopeValue(this.pop, selectKey, traverser);
- bindings.put(selectKey, TraversalUtil.applyNullable(end, this.traversalRing.next()));
+ final TraversalProduct product = TraversalUtil.produce(end, this.traversalRing.next());
+
+ if (!product.isProductive()) break;
+
+ bindings.put(selectKey, (E) product.get());
}
+
+ // bindings should be the same size as keys or else there was an uproductive by() in which case we filter
+ // with an EmptyTraverser
+ if (bindings.size() != selectKeys.size()) return EmptyTraverser.instance();
+
} catch (KeyNotFoundException nfe) {
return EmptyTraverser.instance();
} finally {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
index 1904859..ee70053 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -81,10 +82,13 @@ public final class TreeStep<S> extends ReducingBarrierStep<S, Tree> implements T
Tree depth = topTree;
final Path path = traverser.path();
for (int i = 0; i < path.size(); i++) {
- final Object object = TraversalUtil.applyNullable(path.<Object>get(i), this.traversalRing.next());
- if (!depth.containsKey(object))
- depth.put(object, new Tree<>());
- depth = (Tree) depth.get(object);
+ final TraversalProduct product = TraversalUtil.produce(path.<Object>get(i), this.traversalRing.next());
+ if (product.isProductive()) {
+ final Object object = product.get();
+ if (!depth.containsKey(object))
+ depth.put(object, new Tree<>());
+ depth = (Tree) depth.get(object);
+ }
}
this.traversalRing.reset();
return topTree;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
index 0f75963..c8fa203 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequire
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.apache.tinkerpop.gremlin.util.function.BulkSetSupplier;
@@ -125,8 +126,11 @@ public final class AggregateGlobalStep<S> extends AbstractStep<S, S> implements
final BulkSet<Object> bulkSet = new BulkSet<>();
while (this.starts.hasNext()) {
final Traverser.Admin<S> traverser = this.starts.next();
- bulkSet.add(TraversalUtil.applyNullable(traverser, this.aggregateTraversal), traverser.bulk());
- traverser.setStepId(this.getNextStep().getId()); // when barrier is reloaded, the traversers should be at the next step
+ TraversalUtil.produce(traverser, aggregateTraversal).ifProductive(p -> bulkSet.add(p, traverser.bulk()));
+
+ traverser.setStepId(this.getNextStep().getId());
+
+ // when barrier is reloaded, the traversers should be at the next step
this.barrier.add(traverser);
}
this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
index 3c7c0fa..7331caf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
@@ -53,7 +53,7 @@ public final class AggregateLocalStep<S> extends SideEffectStep<S> implements Si
@Override
protected void sideEffect(final Traverser.Admin<S> traverser) {
final BulkSet<Object> bulkSet = new BulkSet<>();
- bulkSet.add(TraversalUtil.applyNullable(traverser, this.storeTraversal), traverser.bulk());
+ TraversalUtil.produce(traverser, this.storeTraversal).ifProductive(p -> bulkSet.add(p, traverser.bulk()));
this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
index bd0e828..b19f099 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
@@ -23,7 +23,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -35,7 +38,7 @@ import java.util.function.BiFunction;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
-public final class SackValueStep<S, A, B> extends SideEffectStep<S> implements TraversalParent, ByModulating, LambdaHolder {
+public final class SackValueStep<S, A, B> extends AbstractStep<S, S> implements TraversalParent, ByModulating, LambdaHolder {
private Traversal.Admin<S, B> sackTraversal = null;
@@ -63,8 +66,17 @@ public final class SackValueStep<S, A, B> extends SideEffectStep<S> implements T
}
@Override
- protected void sideEffect(final Traverser.Admin<S> traverser) {
- traverser.sack(this.sackFunction.apply(traverser.sack(), null == this.sackTraversal ? (B) traverser.get() : TraversalUtil.apply(traverser, this.sackTraversal)));
+ protected Traverser.Admin<S> processNextStart() {
+ final Traverser.Admin<S> traverser = this.starts.next();
+ if (null == sackTraversal) {
+ traverser.sack(this.sackFunction.apply(traverser.sack(), (B) traverser.get()));
+ return traverser;
+ } else {
+ final TraversalProduct product = TraversalUtil.produce(traverser, this.sackTraversal);
+ if (!product.isProductive()) return EmptyTraverser.instance();
+ traverser.sack(this.sackFunction.apply(traverser.sack(), (B) product.get()));
+ return traverser;
+ }
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalProduct.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalProduct.java
new file mode 100644
index 0000000..9711d81
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalProduct.java
@@ -0,0 +1,55 @@
+/*
+ * 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.Traversal;
+
+import java.util.function.Consumer;
+
+/**
+ * This class represents the state of the output of a child {@link Traversal} where it is either productive or not.
+ * It is productive if it has at least one traverser within it, even if that traverser is holding a {@code null}.
+ */
+public final class TraversalProduct {
+ public static final TraversalProduct UNPRODUCTIVE = new TraversalProduct();
+ private final Object o;
+ private final boolean productive;
+
+ private TraversalProduct() {
+ this.o = null; // null is valid technically but productive=false trumps it
+ this.productive = false;
+ }
+
+ TraversalProduct(final Object o) {
+ this.o = o;
+ this.productive = true;
+ }
+
+ public Object get() {
+ return o;
+ }
+
+ public boolean isProductive() {
+ return productive;
+ }
+
+ public void ifProductive(final Consumer<Object> c) {
+ if (productive) c.accept(o);
+ }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java
index 4b2b15f..1acb547 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java
@@ -34,12 +34,8 @@ public final class TraversalUtil {
private TraversalUtil() {
}
- public static final <S, E> E apply(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
- final Traverser.Admin<S> split = traverser.split();
- split.setSideEffects(traversal.getSideEffects());
- split.setBulk(1l);
- traversal.reset();
- traversal.addStart(split);
+ public static <S, E> E apply(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ final Traverser<S> split = prepare(traverser, traversal);
try {
return traversal.next(); // map
} catch (final NoSuchElementException e) {
@@ -52,23 +48,43 @@ public final class TraversalUtil {
}
}
- public static final <S, E> Iterator<E> applyAll(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
- final Traverser.Admin<S> split = traverser.split();
- split.setSideEffects(traversal.getSideEffects());
- split.setBulk(1l);
+ public static <S, E> E apply(final S start, final Traversal.Admin<S, E> traversal) {
traversal.reset();
- traversal.addStart(split);
+ traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
+ try {
+ return traversal.next(); // map
+ } catch (final NoSuchElementException e) {
+ throw new IllegalArgumentException("The provided start does not map to a value: " + start + "->" + traversal);
+ } finally {
+ //Close the traversal to release any underlying resources.
+ CloseableIterator.closeIterator(traversal);
+ }
+ }
+
+ public static <S, E> E applyNullable(final S start, final Traversal.Admin<S, E> traversal) {
+ return null == traversal ? (E) start : TraversalUtil.apply(start, traversal);
+ }
+
+ public static <S, E> E applyNullable(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ return null == traversal ? (E) traverser.get() : TraversalUtil.apply(traverser, traversal);
+ }
+
+ public static <S, E> Iterator<E> applyAll(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ prepare(traverser, traversal);
return traversal; // flatmap
}
- public static final <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal, E end) {
+ public static <S, E> Iterator<E> applyAll(final S start, final Traversal.Admin<S, E> traversal) {
+ traversal.reset();
+ traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
+ return traversal; // flatMap
+ }
+
+ public static <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal, E end) {
if (null == end) return TraversalUtil.test(traverser, traversal);
- final Traverser.Admin<S> split = traverser.split();
- split.setSideEffects(traversal.getSideEffects());
- split.setBulk(1l);
- traversal.reset();
- traversal.addStart(split);
+ prepare(traverser, traversal);
+
final Step<?, E> endStep = traversal.getEndStep();
boolean result = false;
while (traversal.hasNext()) {
@@ -85,17 +101,44 @@ public final class TraversalUtil {
return result;
}
- public static final <S, E> E applyNullable(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
- return null == traversal ? (E) traverser.get() : TraversalUtil.apply(traverser, traversal);
+ public static <S, E> TraversalProduct produce(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ if (null == traversal) {
+ return new TraversalProduct(traverser.get());
+ } else {
+ prepare(traverser, traversal);
+ try {
+ if (traversal.hasNext()) {
+ return new TraversalProduct(traversal.next());
+ } else {
+ return TraversalProduct.UNPRODUCTIVE;
+ }
+ } finally {
+ CloseableIterator.closeIterator(traversal);
+ }
+ }
}
- public static final <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
- final Traverser.Admin<S> split = traverser.split();
- split.setSideEffects(traversal.getSideEffects());
- split.setBulk(1l);
- traversal.reset();
- traversal.addStart(split);
- boolean val = traversal.hasNext(); // filter
+ public static <S, E> TraversalProduct produce(final S start, final Traversal.Admin<S, E> traversal) {
+ if (null == traversal) {
+ return new TraversalProduct(start);
+ } else {
+ traversal.reset();
+ traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1L));
+ try {
+ if (traversal.hasNext()) {
+ return new TraversalProduct(traversal.next());
+ } else {
+ return TraversalProduct.UNPRODUCTIVE;
+ }
+ } finally {
+ CloseableIterator.closeIterator(traversal);
+ }
+ }
+ }
+
+ public static <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ prepare(traverser, traversal);
+ final boolean val = traversal.hasNext(); // filter
//Close the traversal to release any underlying resources.
CloseableIterator.closeIterator(traversal);
@@ -103,28 +146,7 @@ public final class TraversalUtil {
return val;
}
- ///////
-
- public static final <S, E> E apply(final S start, final Traversal.Admin<S, E> traversal) {
- traversal.reset();
- traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
- try {
- return traversal.next(); // map
- } catch (final NoSuchElementException e) {
- throw new IllegalArgumentException("The provided start does not map to a value: " + start + "->" + traversal);
- } finally {
- //Close the traversal to release any underlying resources.
- CloseableIterator.closeIterator(traversal);
- }
- }
-
- public static final <S, E> Iterator<E> applyAll(final S start, final Traversal.Admin<S, E> traversal) {
- traversal.reset();
- traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
- return traversal; // flatMap
- }
-
- public static final <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal, final E end) {
+ public static <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal, final E end) {
if (null == end) return TraversalUtil.test(start, traversal);
traversal.reset();
@@ -145,11 +167,7 @@ public final class TraversalUtil {
return result;
}
- public static final <S, E> E applyNullable(final S start, final Traversal.Admin<S, E> traversal) {
- return null == traversal ? (E) start : TraversalUtil.apply(start, traversal);
- }
-
- public static final <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal) {
+ public static <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal) {
traversal.reset();
traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
boolean result = traversal.hasNext(); // filter
@@ -159,4 +177,13 @@ public final class TraversalUtil {
return result;
}
+
+ public static <S, E> Traverser<S> prepare(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ final Traverser.Admin<S> split = traverser.split();
+ split.setSideEffects(traversal.getSideEffects());
+ split.setBulk(1L);
+ traversal.reset();
+ traversal.addStart(split);
+ return split;
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java
index 984767f..1a7b114 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java
@@ -33,7 +33,9 @@ import java.util.stream.Collectors;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @deprecated As of release 3.6.0, not replaced.
*/
+@Deprecated
public final class ChainedComparator<S, C extends Comparable> implements Comparator<S>, Serializable, Cloneable {
private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java
index 4adc701..c28ffc4 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java
@@ -33,6 +33,8 @@ import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -529,4 +531,22 @@ public class PathTest {
assertEquals(1, subPath.labels().get(2).size());
});
}
+
+ @Test
+ public void shouldHandleNullSemanticsCorrectly() {
+ PATH_SUPPLIERS.forEach(supplier -> {
+ final Path p = supplier.get();
+ assertThat(p.isSimple(), is(true));
+ p.extend(null, Collections.emptySet());
+ assertThat(p.isSimple(), is(true));
+ p.extend(1, Collections.emptySet());
+ assertThat(p.isSimple(), is(true));
+ p.extend(null, Collections.emptySet());
+
+ // immutable path won't change so its just going to always be empty and thus always simple
+ if (!(p instanceof ImmutablePath)) {
+ assertThat(p.isSimple(), is(false));
+ }
+ });
+ }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
index 88bb949..47cd52f 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
@@ -43,6 +43,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.coalesce;
import static org.junit.Assert.assertEquals;
@@ -53,9 +54,9 @@ import static org.junit.Assert.assertEquals;
@RunWith(Parameterized.class)
public class PathProcessorStrategyTest {
private static final Translator.ScriptTranslator translator = GroovyTranslator.of("__");
- private static final Collection<TraversalStrategy> withoutProductiveByStrategy =
- TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList().stream().
- filter(s -> s != ProductiveByStrategy.instance()).collect(Collectors.toList());
+ private static final Collection<TraversalStrategy> withProductiveByStrategy =
+ Stream.concat(Stream.of(ProductiveByStrategy.instance()),
+ TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList().stream()).collect(Collectors.toList());
@Parameterized.Parameter(value = 0)
public Traversal.Admin original;
@@ -94,12 +95,12 @@ public class PathProcessorStrategyTest {
{__.select("a").by(__.outE().count()), __.select("a").map(__.outE().count()), Collections.emptyList()},
{__.select("a").by("name"), __.select("a").map(new ValueTraversal<>("name")), Collections.emptyList()},
{__.select("a").out(), __.select("a").out(), Collections.emptyList()},
- {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
- {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
- {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
- {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by("name"), withoutProductiveByStrategy},
- {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").map(__.values("name")), withoutProductiveByStrategy},
- {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").map(__.values("name")), withoutProductiveByStrategy},
+ {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), withProductiveByStrategy},
+ {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), withProductiveByStrategy},
+ {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), withProductiveByStrategy},
+ {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by("name"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+ {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").map(__.values("name")), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+ {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").map(__.values("name")), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
// select("a","b")
{__.select("a", "b"), __.select("a", "b"), Collections.emptyList()},
{__.select("a", "b").by(), __.select("a", "b").by(), Collections.emptyList()},
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
index 412a16f..ace783d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -44,7 +44,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
new Dictionary<string, IgnoreReason>
{
// Add here the name of scenarios to ignore and the reason, e.g.:
- {"g_V_group_byXageX", IgnoreReason.NullKeysInMapNotSupported},
+ {"g_withStrategiesXProductiveByStrategyX_V_group_byXageX", IgnoreReason.NullKeysInMapNotSupported},
+ {"g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX", IgnoreReason.NullKeysInMapNotSupported},
// they are not failing as a result of the Gremlin itself - they are failing because of shortcomings in
// the test suite.
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 8977404..7186968 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -131,6 +131,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_coinX0X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Coin(0.0)}},
{"g_withStrategiesXSeedStrategyX_V_coinX50X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Coin(0.5)}},
{"g_VX1X_outXcreatedX_inXcreatedX_cyclicPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("created").In("created").CyclicPath()}},
+ {"g_VX1X_both_both_cyclicPath_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Both().Both().CyclicPath().By("age")}},
{"g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("created").In("created").CyclicPath().Path()}},
{"g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("created").As("b").In("created").As("c").CyclicPath().From("a").To("b").Path()}},
{"g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(0).V().Both().Coalesce<object>(__.Has("name","marko").Both(),__.Constant<object>(0)).CyclicPath().Path()}},
@@ -155,6 +156,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_both_properties_dedup_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Properties<object>().Dedup().Count()}},
{"g_V_both_properties_properties_dedup_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Properties<object>().Properties<object>().Dedup().Count()}},
{"g_V_order_byXname_descX_barrier_dedup_age_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By("name",Order.Desc).Barrier().Dedup().By("age").Values<object>("name")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Order().By("name",Order.Desc).Barrier().Dedup().By("age").Values<object>("name")}},
+ {"g_V_both_dedup_age_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Dedup().By("age").Values<object>("name")}},
+ {"g_V_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Both().As("b").Both().As("c").Dedup("a","b").By("age").Select<object>("a","b","c").By("name")}},
{"g_V_drop", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV().As("a").AddV().As("b").AddE("knows").To("a"), (g,p) =>g.V().Drop(), (g,p) =>g.V(), (g,p) =>g.E()}},
{"g_V_outE_drop", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV().As("a").AddV().As("b").AddE("knows").To("a"), (g,p) =>g.V().OutE().Drop(), (g,p) =>g.V(), (g,p) =>g.E()}},
{"g_V_properties_drop", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV().Property("name","bob").AddV().Property("name","alice"), (g,p) =>g.V().Properties<object>().Drop(), (g,p) =>g.V(), (g,p) =>g.V().Properties<object>()}},
@@ -281,10 +285,12 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_localXoutE_sampleX1X_byXweightXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.OutE().Sample(1).By("weight"))}},
{"g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_sampleX2X_foldXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Group<object,object>().By(T.Label).By(__.BothE().Values<object>("weight").Order().Sample(2).Fold()).Unfold<object>()}},
{"g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_fold_sampleXlocal_5XXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Group<object,object>().By(T.Label).By(__.BothE().Values<object>("weight").Order().Fold().Sample(Scope.Local,5)).Unfold<object>()}},
+ {"g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Order().By(T.Label,Order.Desc).Sample(1).By("age")}},
{"g_VX1X_outXcreatedX_inXcreatedX_simplePath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("created").In("created").SimplePath()}},
{"g_V_repeatXboth_simplePathX_timesX3X_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat(__.Both().SimplePath()).Times(3).Path()}},
{"g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Out().As("b").Out().As("c").SimplePath().By(T.Label).From("b").To("c").Path().By("name")}},
{"g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_simplePath_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(0).V().Both().Coalesce<object>(__.Has("name","marko").Both(),__.Constant<object>(0)).SimplePath().Path()}},
+ {"g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().As("a").Both().As("b").SimplePath().Path().By("age").From("a").To("b")}},
{"g_V_valuesXnameX_order_tailXglobal_2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Tail<object>(Scope.Global,2)}},
{"g_V_valuesXnameX_order_tailX2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Tail<object>(2)}},
{"g_V_valuesXnameX_order_tail", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Tail<object>()}},
@@ -323,6 +329,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").OutE("created").As("b").InV().As("c").In("created").As("d").Where("a",P.Lt("b").Or(P.Gt("c")).And(P.Neq("d"))).By("age").By("weight").By(__.In("created").Values<object>("age").Min<object>()).Select<object>("a","c [...]
{"g_VX1X_asXaX_out_hasXageX_whereXgtXaXX_byXageX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out().Has("age").Where(P.Gt("a")).By("age").Values<object>("name")}},
{"g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid3"]).As("a").In().Out().As("b").Where("a",P.Eq("b")).By("age").Values<object>("name")}},
+ {"g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V(p["vid3"]).As("a").In().Out().As("b").Where("a",P.Eq("b")).By("age").Values<object>("name")}},
{"g_V_coworker", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).Aggregate("p").As("p1").Values<object>("name").As("p1n").Select<object>("p").Unfold<object>().Where(P.Neq("p1")).As("p2").Values<object>("name").As("p2n").Select<object>("p2").Out("created").Choose<object>(__.In("created").Where(P.Eq("p1")),__.Values<object>("name"),__.Constant<object>(p["xx1"])).Group<object,object>(). [...]
{"g_V_coworker_with_midV", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).As("p1").V().HasLabel("person").Where(P.Neq("p1")).Filter(__.OutE("created")).As("p2").Map<object>(__.Out("created").Where(__.In("created").As("p1")).Values<object>("name").Fold()).Group<object,object>().By(__.Select<object>("p1").By("name")).By(__.Group<object,object>().By(__.Select<object>("p2").By("name")). [...]
{"g_V_playlist_paths", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("name","Bob_Dylan").In("sungBy").Order().By("name").As("a").Repeat(__.Out().Order().By("name").SimplePath().From("a")).Until(__.Out("writtenBy").Has("name","Johnny_Cash")).Limit<object>(1).As("b").Repeat(__.Out().Order().By("name").As("c").SimplePath().From("b").To("c")).Until(__.Out("sungBy").Has("name","Grateful_Dead")).Limit<object>(1).Path().From("a") [...]
@@ -451,6 +458,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_asXaX_outXcreatedX_asXbX_mathXb_plus_aX_byXinXcreatedX_countX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Out("created").As("b").Math("b + a").By(__.In("created").Count()).By("age")}},
{"g_withSackX1X_injectX1X_repeatXsackXsumX_byXconstantX1XXX_timesX5X_emit_mathXsin__X_byXsackX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSack(1).Inject(1).Repeat(__.Sack(Operator.Sum).By(__.Constant<object>(1))).Times(5).Emit().Math("sin _").By(__.Sack<object>())}},
{"g_V_projectXa_b_cX_byXbothE_weight_sumX_byXbothE_countX_byXnameX_order_byXmathXa_div_bX_descX_selectXcX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Project<object>("a","b","c").By(__.BothE().Values<object>("weight").Sum<object>()).By(__.BothE().Count()).By("name").Order().By(__.Math("a / b"),Order.Desc).Select<object>("c")}},
+ {"g_V_mathXit_plus_itXbyXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Math("_+_").By("age")}},
+ {"g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>().Math("_+_").By(__.Select<object>("age").Unfold<object>())}},
{"g_V_age_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Max<object>()}},
{"g_V_foo_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Max<object>()}},
{"g_V_name_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Max<object>()}},
@@ -460,7 +469,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_aggregateXaX_byXageX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Max<object>()}},
{"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Max<object>()}},
{"g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Max<object>(Scope.Local)}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Max<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXfooX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Max<object>()}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Max<object>()}},
{"g_V_foo_fold_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Max<object>(Scope.Local)}},
{"g_V_name_fold_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Fold().Max<object>(Scope.Local)}},
{"g_V_repeatXbothX_timesX5X_age_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat(__.Both()).Times(5).Values<object>("age").Max<object>()}},
@@ -471,9 +482,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_foo_fold_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Mean<object>(Scope.Local)}},
{"g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_meanX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("software").Group<object,object>().By("name").By(__.BothE().Values<object>("weight").Mean<object>())}},
{"g_V_aggregateXaX_byXageX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Mean<object>(Scope.Local)}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Mean<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXageX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Mean<object>()}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Mean<object>()}},
{"g_V_aggregateXaX_byXfooX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Mean<object>(Scope.Local)}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Mean<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXfooX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Mean<object>()}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Mean<object>()}},
{"g_injectXnull_10_20_nullX_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null,p["xx1"],p["xx2"],null).Mean<object>()}},
{"g_injectXlistXnull_10_20_nullXX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Mean<object>(Scope.Local)}},
{"g_V_age_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Min<object>()}},
@@ -481,9 +496,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_name_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Min<object>()}},
{"g_V_age_fold_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Fold().Min<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXageX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Min<object>(Scope.Local)}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Min<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXageX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Min<object>()}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Min<object>()}},
{"g_V_aggregateXaX_byXfooX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Min<object>(Scope.Local)}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Min<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXfooX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Min<object>()}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Min<object>()}},
{"g_V_foo_fold_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Min<object>(Scope.Local)}},
{"g_V_name_fold_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Fold().Min<object>(Scope.Local)}},
{"g_V_repeatXbothX_timesX5X_age_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat(__.Both()).Times(5).Values<object>("age").Min<object>()}},
@@ -508,11 +527,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_both_hasLabelXpersonX_order_byXage_descX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().HasLabel("person").Order().By("age",Order.Desc).Values<object>("name")}},
{"g_V_order_byXoutE_count_descX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By(__.OutE().Count(),Order.Desc)}},
{"g_V_hasLabelXpersonX_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Order().By("age")}},
+ {"g_V_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By("age")}},
+ {"g_V_fold_orderXlocalX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fold().Order(Scope.Local).By("age")}},
+ {"g_V_fold_orderXlocalX_byXage_descX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fold().Order(Scope.Local).By("age",Order.Desc)}},
{"g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Or(__.HasLabel("person"),__.Has("software","name","lop")).Order().By("age")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Or(__.HasLabel("person"),__.Has("software","name","lop")).Order().By("age")}},
{"g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v1"]).HasLabel("person").Map<object>((IFunction) p["l1"]).Order(Scope.Local).By(Column.Values,Order.Desc).By(Column.Keys,Order.Asc)}},
{"g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("song","name","OH BOY").Out("followedBy").Out("followedBy").Order().By("performances").By("songType",Order.Desc).By("name")}},
{"g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("song").Order().By("performances",Order.Desc).By("name").Range<object>(110,120).Values<object>("name")}},
{"g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ElementMap<object>().Order(Scope.Local).By(Column.Keys,Order.Desc).Unfold<object>()}},
+ {"g_VX1X_elementMap_orderXlocalX_byXkeys_ascXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ElementMap<object>().Order(Scope.Local).By(Column.Keys,Order.Asc).Unfold<object>()}},
{"g_V_pageRank_hasXpageRankX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().PageRank().Has("gremlin.pageRankVertexProgram.pageRank")}},
{"g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").PageRank().With("~tinkerpop.pageRank.edges",__.BothE()).With("~tinkerpop.pageRank.propertyName","projectRank").With("~tinkerpop.pageRank.times",0).ValueMap<object,object>("name","projectRank")}},
{"g_V_pageRank_order_byXpageRank_descX_byXnameX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().PageRank().Order().By("gremlin.pageRankVertexProgram.pageRank",Order.Desc).By("name").Values<object>("name")}},
@@ -530,6 +554,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_VX1X_outEXcreatedX_inV_inE_outV_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE("created").InV().InE().OutV().Path()}},
{"g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Out().As("b").Out().As("c").Path().From("b").To("c").By("name")}},
{"g_VX1X_out_path_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().Path().By("age")}},
+ {"g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V(p["vid1"]).Out().Path().By("age")}},
{"g_injectX1_null_nullX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(1,null,null).Path()}},
{"g_injectX1_null_nullX_path_dedup", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(1,null,null).Path().Dedup()}},
{"g_V_peerPressure_hasXclusterX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().PeerPressure().Has("gremlin.peerPressureVertexProgram.cluster")}},
@@ -539,6 +564,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__descX_selectXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").Project<object>("a","b").By("name").By(__.In("created").Count()).Order().By(__.Select<object>("b"),Order.Desc).Select<object>("a")}},
{"g_V_valueMap_projectXxX_byXselectXnameXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>().Project<object>("x").By(__.Select<object>("name"))}},
{"g_V_projectXa_bX_byXinE_countX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Project<object>("a","b").By(__.InE().Count()).By("age")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Project<object>("a","b").By(__.InE().Count()).By("age")}},
{"g_V_hasXageX_propertiesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name").Value<object>()}},
{"g_V_hasXageX_propertiesXname_ageX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name","age").Value<object>()}},
{"g_V_hasXageX_propertiesXage_nameX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("age","name").Value<object>()}},
@@ -607,6 +633,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).Properties<object>("weight").As("a").Select<object>("a").By(T.Key)}},
{"g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).Properties<object>("weight").As("a").Select<object>("a").By(T.Value)}},
{"g_V_asXaX_selectXaX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Select<object>("a").By("age")}},
+ {"g_V_asXa_nX_selectXa_nX_byXageX_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a","n").Select<object>("a","n").By("age").By("name")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().As("a").Select<object>("a").By("age")}},
{"g_withSideEffectXk_nullX_injectXxX_selectXkX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSideEffect("k",null).Inject("x").Select<object>("k")}},
{"g_V_shortestPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Identity().ShortestPath()}},
{"g_V_both_dedup_shortestPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Dedup().ShortestPath()}},
@@ -629,9 +657,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_foo_fold_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Sum<object>(Scope.Local)}},
{"g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_sumX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("software").Group<object,object>().By("name").By(__.BothE().Values<object>("weight").Sum<object>())}},
{"g_V_aggregateXaX_byXageX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Sum<object>(Scope.Local)}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Sum<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXageX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Sum<object>()}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Sum<object>()}},
{"g_V_aggregateXaX_byXfooX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Sum<object>(Scope.Local)}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Sum<object>(Scope.Local)}},
{"g_V_aggregateXaX_byXfooX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Sum<object>()}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Sum<object>()}},
{"g_injectXnull_10_5_nullX_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null,p["xx1"],p["xx2"],null).Sum<object>()}},
{"g_injectXlistXnull_10_5_nullXX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Sum<object>(Scope.Local)}},
{"g_V_localXoutE_foldX_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.OutE().Fold()).Unfold<object>()}},
@@ -650,6 +682,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).ValueMap<object,object>().With("~tinkerpop.valueMap.tokens")}},
{"g_VX1X_valueMapXname_locationX_byXunfoldX_by", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ValueMap<object,object>("name","location").By(__.Unfold<object>()).By()}},
{"g_V_valueMapXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>("name","age",null)}},
+ {"g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>("name","age").By(__.Is("x")).By(__.Unfold<object>())}},
{"g_VXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(null)}},
{"g_VXlistXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"])}},
{"g_VX1_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"],null)}},
@@ -711,17 +744,24 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_aggregateXxX_byXnameX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By("name").Cap<object>("x")}},
{"g_V_out_aggregateXaX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().Aggregate("a").Path()}},
{"g_V_hasLabelXpersonX_aggregateXxX_byXageX_capXxX_asXyX_selectXyX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Aggregate("x").By("age").Cap<object>("x").As("y").Select<object>("y")}},
+ {"g_V_aggregateXxX_byXageX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By("age").Cap<object>("x")}},
+ {"g_V_aggregateXlocal_xX_byXageX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate(Scope.Local,"x").By("age").Cap<object>("x")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate(Scope.Local,"x").By("age").Cap<object>("x")}},
{"g_V_aggregateXlocal_a_nameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate(Scope.Local,"a").By("name").Out().Cap<object>("a")}},
{"g_VX1X_aggregateXlocal_aX_byXnameX_out_aggregateXlocal_aX_byXnameX_name_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Aggregate(Scope.Local,"a").By("name").Out().Aggregate(Scope.Local,"a").By("name").Values<object>("name").Cap<object>("a")}},
{"g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSideEffect("a",p["xx1"]).V().Both().Values<object>("name").Aggregate(Scope.Local,"a").Cap<object>("a")}},
{"g_V_aggregateXlocal_aX_byXoutEXcreatedX_countX_out_out_aggregateXlocal_aX_byXinEXcreatedX_weight_sumX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate(Scope.Local,"a").By(__.OutE("created").Count()).Out().Out().Aggregate(Scope.Local,"a").By(__.InE("created").Values<object>("weight").Sum<object>()).Cap<object>("a")}},
{"g_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By(__.Values<object>("age").Is(P.Gt(29))).Cap<object>("x")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("x").By(__.Values<object>("age").Is(P.Gt(29))).Cap<object>("x")}},
{"g_V_aggregateXxX_byXout_order_byXnameXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By(__.Out().Order().By("name")).Cap<object>("x")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("x").By(__.Out().Order().By("name")).Cap<object>("x")}},
{"g_V_fail", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fail()}},
{"g_V_failXmsgX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fail("msg")}},
{"g_V_unionXout_failX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Union<object>(__.Out(),__.Fail())}},
{"g_V_group_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("name")}},
{"g_V_group_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("age")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_group_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Group<object,object>().By("age")}},
+ {"g_V_group_byXnameX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("name").By("age")}},
{"g_V_group_byXnameX_by", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("name").By()}},
{"g_V_groupXaX_byXnameX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group("a").By("name").Cap<object>("a")}},
{"g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("lang").Group("a").By("lang").By("name").Out().Cap<object>("a")}},
@@ -745,6 +785,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_group_byXlabelX_byXlabel_countX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By(__.Label()).By(__.Label().Count())}},
{"g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group("m").By(__.Label()).By(__.Label().Count()).Cap<object>("m")}},
{"g_V_outXcreatedX_groupCount_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").GroupCount<object>().By("name")}},
+ {"g_V_groupCount_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().GroupCount<object>().By("age")}},
+ {"g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().GroupCount<object>().By("age")}},
{"g_V_outXcreatedX_name_groupCount", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").Values<object>("name").GroupCount<object>()}},
{"g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").GroupCount("a").By("name").Cap<object>("a")}},
{"g_V_outXcreatedX_name_groupCountXaX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").Values<object>("name").GroupCount("a").Cap<object>("a")}},
@@ -783,6 +825,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_withBulkXfalseX_withSackX1_sumX_VX1X_localXoutEXknowsX_barrierXnormSackX_inVX_inXknowsX_barrier_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithBulk(false).WithSack(1.0,Operator.Sum).V(p["vid1"]).Local<object>(__.OutE("knows").Barrier(Barrier.NormSack).InV()).In("knows").Barrier().Sack<object>()}},
{"g_withBulkXfalseX_withSackX1_sumX_V_out_barrier_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithBulk(false).WithSack(1,Operator.Sum).V().Out().Barrier().Sack<object>()}},
{"g_withSackX1_sumX_VX1X_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSack(1.0,Operator.Sum).V(p["vid1"]).Local<object>(__.Out("knows").Barrier(Barrier.NormSack)).In("knows").Barrier().Sack<object>()}},
+ {"g_V_sackXassignX_byXageX_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Sack(Operator.Assign).By("age").Sack<object>()}},
{"g_V_hasXageX_groupCountXaX_byXnameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").GroupCount("a").By("name").Out().Cap<object>("a")}},
{"g_V_storeXa_nameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Store("a").By("name").Out().Cap<object>("a")}},
{"g_VX1X_storeXaX_byXnameX_out_storeXaX_byXnameX_name_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Store("a").By("name").Out().Store("a").By("name").Values<object>("name").Cap<object>("a")}},
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index 5205f85..90f63ff 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -68,7 +68,7 @@ const ignoredScenarios = {
// An associative array containing the scenario name as key, for example:
'g_withSideEffectXa_setX_V_both_name_storeXaX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
'g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
- 'g_V_group_byXageX': new IgnoreError(ignoreReason.nullKeysInMapNotSupportedWell),
+ 'g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX': new IgnoreError(ignoreReason.nullKeysInMapNotSupportedWell),
'g_V_shortestPath_edgesIncluded': new IgnoreError(ignoreReason.needsFurtherInvestigation),
'g_V_shortestPath_edgesIncluded_edgesXoutEX': new IgnoreError(ignoreReason.needsFurtherInvestigation),
'g_V_shortestpath': new IgnoreError(ignoreReason.needsFurtherInvestigation)
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index d303f97..ea908b0 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -119,6 +119,7 @@ const gremlins = {
g_V_coinX0X: [function({g}) { return g.V().coin(0.0) }],
g_withStrategiesXSeedStrategyX_V_coinX50X: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().coin(0.5) }],
g_VX1X_outXcreatedX_inXcreatedX_cyclicPath: [function({g, vid1}) { return g.V(vid1).out("created").in_("created").cyclicPath() }],
+ g_VX1X_both_both_cyclicPath_byXageX: [function({g, vid1}) { return g.V(vid1).both().both().cyclicPath().by("age") }],
g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path: [function({g, vid1}) { return g.V(vid1).out("created").in_("created").cyclicPath().path() }],
g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path: [function({g, vid1}) { return g.V(vid1).as("a").out("created").as("b").in_("created").as("c").cyclicPath().from_("a").to("b").path() }],
g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path: [function({g}) { return g.inject(0).V().both().coalesce(__.has("name","marko").both(),__.constant(0)).cyclicPath().path() }],
@@ -143,6 +144,9 @@ const gremlins = {
g_V_both_properties_dedup_count: [function({g}) { return g.V().both().properties().dedup().count() }],
g_V_both_properties_properties_dedup_count: [function({g}) { return g.V().both().properties().properties().dedup().count() }],
g_V_order_byXname_descX_barrier_dedup_age_name: [function({g}) { return g.V().order().by("name",Order.desc).barrier().dedup().by("age").values("name") }],
+ g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().order().by("name",Order.desc).barrier().dedup().by("age").values("name") }],
+ g_V_both_dedup_age_name: [function({g}) { return g.V().both().dedup().by("age").values("name") }],
+ g_V_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name: [function({g}) { return g.V().as("a").both().as("b").both().as("c").dedup("a","b").by("age").select("a","b","c").by("name") }],
g_V_drop: [function({g}) { return g.addV().as("a").addV().as("b").addE("knows").to("a") }, function({g}) { return g.V().drop() }, function({g}) { return g.V() }, function({g}) { return g.E() }],
g_V_outE_drop: [function({g}) { return g.addV().as("a").addV().as("b").addE("knows").to("a") }, function({g}) { return g.V().outE().drop() }, function({g}) { return g.V() }, function({g}) { return g.E() }],
g_V_properties_drop: [function({g}) { return g.addV().property("name","bob").addV().property("name","alice") }, function({g}) { return g.V().properties().drop() }, function({g}) { return g.V() }, function({g}) { return g.V().properties() }],
@@ -269,10 +273,12 @@ const gremlins = {
g_V_localXoutE_sampleX1X_byXweightXX: [function({g}) { return g.V().local(__.outE().sample(1).by("weight")) }],
g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_sampleX2X_foldXunfold: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().group().by(T.label).by(__.bothE().values("weight").order().sample(2).fold()).unfold() }],
g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_fold_sampleXlocal_5XXunfold: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().group().by(T.label).by(__.bothE().values("weight").order().fold().sample(Scope.local,5)).unfold() }],
+ g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().order().by(T.label,Order.desc).sample(1).by("age") }],
g_VX1X_outXcreatedX_inXcreatedX_simplePath: [function({g, vid1}) { return g.V(vid1).out("created").in_("created").simplePath() }],
g_V_repeatXboth_simplePathX_timesX3X_path: [function({g}) { return g.V().repeat(__.both().simplePath()).times(3).path() }],
g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX: [function({g}) { return g.V().as("a").out().as("b").out().as("c").simplePath().by(T.label).from_("b").to("c").path().by("name") }],
g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_simplePath_path: [function({g}) { return g.inject(0).V().both().coalesce(__.has("name","marko").both(),__.constant(0)).simplePath().path() }],
+ g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX: [function({g}) { return g.V().both().as("a").both().as("b").simplePath().path().by("age").from_("a").to("b") }],
g_V_valuesXnameX_order_tailXglobal_2X: [function({g}) { return g.V().values("name").order().tail(Scope.global,2) }],
g_V_valuesXnameX_order_tailX2X: [function({g}) { return g.V().values("name").order().tail(2) }],
g_V_valuesXnameX_order_tail: [function({g}) { return g.V().values("name").order().tail() }],
@@ -311,6 +317,7 @@ const gremlins = {
g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX: [function({g}) { return g.V().as("a").outE("created").as("b").inV().as("c").in_("created").as("d").where("a",P.lt("b").or(P.gt("c")).and(P.neq("d"))).by("age").by("weight").by(__.in_("created").values("age").min()).select("a","c","d").by("name") }],
g_VX1X_asXaX_out_hasXageX_whereXgtXaXX_byXageX_name: [function({g, vid1}) { return g.V(vid1).as("a").out().has("age").where(P.gt("a")).by("age").values("name") }],
g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name: [function({g, vid3}) { return g.V(vid3).as("a").in_().out().as("b").where("a",P.eq("b")).by("age").values("name") }],
+ g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name: [function({g, vid3}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V(vid3).as("a").in_().out().as("b").where("a",P.eq("b")).by("age").values("name") }],
g_V_coworker: [function({g, xx1}) { return g.V().hasLabel("person").filter(__.outE("created")).aggregate("p").as("p1").values("name").as("p1n").select("p").unfold().where(P.neq("p1")).as("p2").values("name").as("p2n").select("p2").out("created").choose(__.in_("created").where(P.eq("p1")),__.values("name"),__.constant(xx1)).group().by(__.select("p1n")).by(__.group().by(__.select("p2n")).by(__.unfold().fold().project("numCoCreated","coCreated").by(__.count(Scope.local)).by())).unfold() }],
g_V_coworker_with_midV: [function({g}) { return g.V().hasLabel("person").filter(__.outE("created")).as("p1").V().hasLabel("person").where(P.neq("p1")).filter(__.outE("created")).as("p2").map(__.out("created").where(__.in_("created").as("p1")).values("name").fold()).group().by(__.select("p1").by("name")).by(__.group().by(__.select("p2").by("name")).by(__.project("numCoCreated","coCreated").by(__.count(Scope.local)).by())).unfold() }],
g_V_playlist_paths: [function({g}) { return g.V().has("name","Bob_Dylan").in_("sungBy").order().by("name").as("a").repeat(__.out().order().by("name").simplePath().from_("a")).until(__.out("writtenBy").has("name","Johnny_Cash")).limit(1).as("b").repeat(__.out().order().by("name").as("c").simplePath().from_("b").to("c")).until(__.out("sungBy").has("name","Grateful_Dead")).limit(1).path().from_("a").unfold().project("song","artists").by("name").by(__.coalesce(__.out("sungBy","writtenBy" [...]
@@ -439,14 +446,20 @@ const gremlins = {
g_V_asXaX_outXcreatedX_asXbX_mathXb_plus_aX_byXinXcreatedX_countX_byXageX: [function({g}) { return g.V().as("a").out("created").as("b").math("b + a").by(__.in_("created").count()).by("age") }],
g_withSackX1X_injectX1X_repeatXsackXsumX_byXconstantX1XXX_timesX5X_emit_mathXsin__X_byXsackX: [function({g}) { return g.withSack(1).inject(1).repeat(__.sack(Operator.sum).by(__.constant(1))).times(5).emit().math("sin _").by(__.sack()) }],
g_V_projectXa_b_cX_byXbothE_weight_sumX_byXbothE_countX_byXnameX_order_byXmathXa_div_bX_descX_selectXcX: [function({g}) { return g.V().project("a","b","c").by(__.bothE().values("weight").sum()).by(__.bothE().count()).by("name").order().by(__.math("a / b"),Order.desc).select("c") }],
+ g_V_mathXit_plus_itXbyXageX: [function({g}) { return g.V().math("_+_").by("age") }],
+ g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX: [function({g}) { return g.V().valueMap().math("_+_").by(__.select("age").unfold()) }],
g_V_age_max: [function({g}) { return g.V().values("age").max() }],
g_V_foo_max: [function({g}) { return g.V().values("foo").max() }],
g_V_name_max: [function({g}) { return g.V().values("name").max() }],
g_V_age_fold_maxXlocalX: [function({g}) { return g.V().values("age").fold().max(Scope.local) }],
g_V_aggregateXaX_byXageX_capXaX_maxXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").max(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_maxXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").max(Scope.local) }],
g_V_aggregateXaX_byXageX_capXaX_unfold_max: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().max() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().max() }],
g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").max(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").max(Scope.local) }],
g_V_aggregateXaX_byXfooX_capXaX_unfold_max: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().max() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().max() }],
g_V_foo_fold_maxXlocalX: [function({g}) { return g.V().values("foo").fold().max(Scope.local) }],
g_V_name_fold_maxXlocalX: [function({g}) { return g.V().values("name").fold().max(Scope.local) }],
g_V_repeatXbothX_timesX5X_age_max: [function({g}) { return g.V().repeat(__.both()).times(5).values("age").max() }],
@@ -457,9 +470,13 @@ const gremlins = {
g_V_foo_fold_meanXlocalX: [function({g}) { return g.V().values("foo").fold().mean(Scope.local) }],
g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_meanX: [function({g}) { return g.V().hasLabel("software").group().by("name").by(__.bothE().values("weight").mean()) }],
g_V_aggregateXaX_byXageX_meanXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").mean(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").mean(Scope.local) }],
g_V_aggregateXaX_byXageX_capXaX_unfold_mean: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().mean() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().mean() }],
g_V_aggregateXaX_byXfooX_meanXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").mean(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").mean(Scope.local) }],
g_V_aggregateXaX_byXfooX_capXaX_unfold_mean: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().mean() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().mean() }],
g_injectXnull_10_20_nullX_mean: [function({g, xx1, xx2}) { return g.inject(null,xx1,xx2,null).mean() }],
g_injectXlistXnull_10_20_nullXX_meanXlocalX: [function({g, xx1}) { return g.inject(xx1).mean(Scope.local) }],
g_V_age_min: [function({g}) { return g.V().values("age").min() }],
@@ -467,9 +484,13 @@ const gremlins = {
g_V_name_min: [function({g}) { return g.V().values("name").min() }],
g_V_age_fold_minXlocalX: [function({g}) { return g.V().values("age").fold().min(Scope.local) }],
g_V_aggregateXaX_byXageX_capXaX_minXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").min(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").min(Scope.local) }],
g_V_aggregateXaX_byXageX_capXaX_unfold_min: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().min() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().min() }],
g_V_aggregateXaX_byXfooX_capXaX_minXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").min(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").min(Scope.local) }],
g_V_aggregateXaX_byXfooX_capXaX_unfold_min: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().min() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().min() }],
g_V_foo_fold_minXlocalX: [function({g}) { return g.V().values("foo").fold().min(Scope.local) }],
g_V_name_fold_minXlocalX: [function({g}) { return g.V().values("name").fold().min(Scope.local) }],
g_V_repeatXbothX_timesX5X_age_min: [function({g}) { return g.V().repeat(__.both()).times(5).values("age").min() }],
@@ -494,11 +515,14 @@ const gremlins = {
g_V_both_hasLabelXpersonX_order_byXage_descX_name: [function({g}) { return g.V().both().hasLabel("person").order().by("age",Order.desc).values("name") }],
g_V_order_byXoutE_count_descX: [function({g}) { return g.V().order().by(__.outE().count(),Order.desc) }],
g_V_hasLabelXpersonX_order_byXageX: [function({g}) { return g.V().hasLabel("person").order().by("age") }],
+ g_V_order_byXageX: [function({g}) { return g.V().order().by("age") }],
+ g_V_fold_orderXlocalX_byXageX: [function({g}) { return g.V().fold().order(Scope.local).by("age") }, function({g}) { return g.V().fold().order(Scope.local).by("age",Order.desc) }],
g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX: [function({g}) { return g.V().or(__.hasLabel("person"),__.has("software","name","lop")).order().by("age") }],
+ g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().or(__.hasLabel("person"),__.has("software","name","lop")).order().by("age") }],
g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX: [function({g, l1, v1}) { return g.V(v1).hasLabel("person").map(l1).order(Scope.local).by(Column.values,Order.desc).by(Column.keys,Order.asc) }],
g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX: [function({g}) { return g.V().has("song","name","OH BOY").out("followedBy").out("followedBy").order().by("performances").by("songType",Order.desc).by("name") }],
g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name: [function({g}) { return g.V().hasLabel("song").order().by("performances",Order.desc).by("name").range(110,120).values("name") }],
- g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold: [function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.desc).unfold() }],
+ g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold: [function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.desc).unfold() }, function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.asc).unfold() }],
g_V_pageRank_hasXpageRankX: [function({g}) { return g.V().pageRank().has("gremlin.pageRankVertexProgram.pageRank") }],
g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX: [function({g}) { return g.V().out("created").pageRank().with_("~tinkerpop.pageRank.edges",__.bothE()).with_("~tinkerpop.pageRank.propertyName","projectRank").with_("~tinkerpop.pageRank.times",0).valueMap("name","projectRank") }],
g_V_pageRank_order_byXpageRank_descX_byXnameX_name: [function({g}) { return g.V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank",Order.desc).by("name").values("name") }],
@@ -516,6 +540,7 @@ const gremlins = {
g_VX1X_outEXcreatedX_inV_inE_outV_path: [function({g, vid1}) { return g.V(vid1).outE("created").inV().inE().outV().path() }],
g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX: [function({g}) { return g.V().as("a").out().as("b").out().as("c").path().from_("b").to("c").by("name") }],
g_VX1X_out_path_byXageX: [function({g, vid1}) { return g.V(vid1).out().path().by("age") }],
+ g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX: [function({g, vid1}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V(vid1).out().path().by("age") }],
g_injectX1_null_nullX_path: [function({g}) { return g.inject(1,null,null).path() }],
g_injectX1_null_nullX_path_dedup: [function({g}) { return g.inject(1,null,null).path().dedup() }],
g_V_peerPressure_hasXclusterX: [function({g}) { return g.V().peerPressure().has("gremlin.peerPressureVertexProgram.cluster") }],
@@ -525,6 +550,7 @@ const gremlins = {
g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__descX_selectXaX: [function({g}) { return g.V().out("created").project("a","b").by("name").by(__.in_("created").count()).order().by(__.select("b"),Order.desc).select("a") }],
g_V_valueMap_projectXxX_byXselectXnameXX: [function({g}) { return g.V().valueMap().project("x").by(__.select("name")) }],
g_V_projectXa_bX_byXinE_countX_byXageX: [function({g}) { return g.V().project("a","b").by(__.inE().count()).by("age") }],
+ g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().project("a","b").by(__.inE().count()).by("age") }],
g_V_hasXageX_propertiesXnameX: [function({g}) { return g.V().has("age").properties("name").value() }],
g_V_hasXageX_propertiesXname_ageX_value: [function({g}) { return g.V().has("age").properties("name","age").value() }],
g_V_hasXageX_propertiesXage_nameX_value: [function({g}) { return g.V().has("age").properties("age","name").value() }],
@@ -593,6 +619,8 @@ const gremlins = {
g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.key) }],
g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.value) }],
g_V_asXaX_selectXaX_byXageX: [function({g}) { return g.V().as("a").select("a").by("age") }],
+ g_V_asXa_nX_selectXa_nX_byXageX_byXnameX: [function({g}) { return g.V().as("a","n").select("a","n").by("age").by("name") }],
+ g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().as("a").select("a").by("age") }],
g_withSideEffectXk_nullX_injectXxX_selectXkX: [function({g}) { return g.withSideEffect("k",null).inject("x").select("k") }],
g_V_shortestPath: [function({g}) { return g.V().identity().shortestPath() }],
g_V_both_dedup_shortestPath: [function({g}) { return g.V().both().dedup().shortestPath() }],
@@ -615,9 +643,13 @@ const gremlins = {
g_V_foo_fold_sumXlocalX: [function({g}) { return g.V().values("foo").fold().sum(Scope.local) }],
g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_sumX: [function({g}) { return g.V().hasLabel("software").group().by("name").by(__.bothE().values("weight").sum()) }],
g_V_aggregateXaX_byXageX_sumXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").sum(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").sum(Scope.local) }],
g_V_aggregateXaX_byXageX_capXaX_unfold_sum: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().sum() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().sum() }],
g_V_aggregateXaX_byXfooX_sumXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").sum(Scope.local) }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").sum(Scope.local) }],
g_V_aggregateXaX_byXfooX_capXaX_unfold_sum: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().sum() }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().sum() }],
g_injectXnull_10_5_nullX_sum: [function({g, xx1, xx2}) { return g.inject(null,xx1,xx2,null).sum() }],
g_injectXlistXnull_10_5_nullXX_sumXlocalX: [function({g, xx1}) { return g.inject(xx1).sum(Scope.local) }],
g_V_localXoutE_foldX_unfold: [function({g}) { return g.V().local(__.outE().fold()).unfold() }],
@@ -636,6 +668,7 @@ const gremlins = {
g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX: [function({g}) { return g.V().hasLabel("person").filter(__.outE("created")).valueMap().with_("~tinkerpop.valueMap.tokens") }],
g_VX1X_valueMapXname_locationX_byXunfoldX_by: [function({g, vid1}) { return g.V(vid1).valueMap("name","location").by(__.unfold()).by() }],
g_V_valueMapXname_age_nullX: [function({g}) { return g.V().valueMap("name","age",null) }],
+ g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX: [function({g}) { return g.V().valueMap("name","age").by(__.is("x")).by(__.unfold()) }],
g_VXnullX: [function({g}) { return g.V(null) }],
g_VXlistXnullXX: [function({g, xx1}) { return g.V(xx1) }],
g_VX1_nullX: [function({g, vid1}) { return g.V(vid1,null) }],
@@ -697,17 +730,24 @@ const gremlins = {
g_V_aggregateXxX_byXnameX_capXxX: [function({g}) { return g.V().aggregate("x").by("name").cap("x") }],
g_V_out_aggregateXaX_path: [function({g}) { return g.V().out().aggregate("a").path() }],
g_V_hasLabelXpersonX_aggregateXxX_byXageX_capXxX_asXyX_selectXyX: [function({g}) { return g.V().hasLabel("person").aggregate("x").by("age").cap("x").as("y").select("y") }],
+ g_V_aggregateXxX_byXageX_capXxX: [function({g}) { return g.V().aggregate("x").by("age").cap("x") }],
+ g_V_aggregateXlocal_xX_byXageX_capXxX: [function({g}) { return g.V().aggregate(Scope.local,"x").by("age").cap("x") }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate(Scope.local,"x").by("age").cap("x") }],
g_V_aggregateXlocal_a_nameX_out_capXaX: [function({g}) { return g.V().aggregate(Scope.local,"a").by("name").out().cap("a") }],
g_VX1X_aggregateXlocal_aX_byXnameX_out_aggregateXlocal_aX_byXnameX_name_capXaX: [function({g, vid1}) { return g.V(vid1).aggregate(Scope.local,"a").by("name").out().aggregate(Scope.local,"a").by("name").values("name").cap("a") }],
g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX: [function({g, xx1}) { return g.withSideEffect("a",xx1).V().both().values("name").aggregate(Scope.local,"a").cap("a") }],
g_V_aggregateXlocal_aX_byXoutEXcreatedX_countX_out_out_aggregateXlocal_aX_byXinEXcreatedX_weight_sumX: [function({g}) { return g.V().aggregate(Scope.local,"a").by(__.outE("created").count()).out().out().aggregate(Scope.local,"a").by(__.inE("created").values("weight").sum()).cap("a") }],
g_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX: [function({g}) { return g.V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x") }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x") }],
g_V_aggregateXxX_byXout_order_byXnameXX_capXxX: [function({g}) { return g.V().aggregate("x").by(__.out().order().by("name")).cap("x") }],
+ g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("x").by(__.out().order().by("name")).cap("x") }],
g_V_fail: [function({g}) { return g.V().fail() }],
g_V_failXmsgX: [function({g}) { return g.V().fail("msg") }],
g_V_unionXout_failX: [function({g}) { return g.V().union(__.out(),__.fail()) }],
g_V_group_byXnameX: [function({g}) { return g.V().group().by("name") }],
g_V_group_byXageX: [function({g}) { return g.V().group().by("age") }],
+ g_withStrategiesXProductiveByStrategyX_V_group_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().group().by("age") }],
+ g_V_group_byXnameX_byXageX: [function({g}) { return g.V().group().by("name").by("age") }],
g_V_group_byXnameX_by: [function({g}) { return g.V().group().by("name").by() }],
g_V_groupXaX_byXnameX_capXaX: [function({g}) { return g.V().group("a").by("name").cap("a") }],
g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX: [function({g}) { return g.V().has("lang").group("a").by("lang").by("name").out().cap("a") }],
@@ -731,6 +771,8 @@ const gremlins = {
g_V_group_byXlabelX_byXlabel_countX: [function({g}) { return g.V().group().by(__.label()).by(__.label().count()) }],
g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX: [function({g}) { return g.V().group("m").by(__.label()).by(__.label().count()).cap("m") }],
g_V_outXcreatedX_groupCount_byXnameX: [function({g}) { return g.V().out("created").groupCount().by("name") }],
+ g_V_groupCount_byXageX: [function({g}) { return g.V().groupCount().by("age") }],
+ g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().groupCount().by("age") }],
g_V_outXcreatedX_name_groupCount: [function({g}) { return g.V().out("created").values("name").groupCount() }],
g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX: [function({g}) { return g.V().out("created").groupCount("a").by("name").cap("a") }],
g_V_outXcreatedX_name_groupCountXaX_capXaX: [function({g}) { return g.V().out("created").values("name").groupCount("a").cap("a") }],
@@ -769,6 +811,7 @@ const gremlins = {
g_withBulkXfalseX_withSackX1_sumX_VX1X_localXoutEXknowsX_barrierXnormSackX_inVX_inXknowsX_barrier_sack: [function({g, vid1}) { return g.withBulk(false).withSack(1.0,Operator.sum).V(vid1).local(__.outE("knows").barrier(Barrier.normSack).inV()).in_("knows").barrier().sack() }],
g_withBulkXfalseX_withSackX1_sumX_V_out_barrier_sack: [function({g}) { return g.withBulk(false).withSack(1,Operator.sum).V().out().barrier().sack() }],
g_withSackX1_sumX_VX1X_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack: [function({g, vid1}) { return g.withSack(1.0,Operator.sum).V(vid1).local(__.out("knows").barrier(Barrier.normSack)).in_("knows").barrier().sack() }],
+ g_V_sackXassignX_byXageX_sack: [function({g}) { return g.V().sack(Operator.assign).by("age").sack() }],
g_V_hasXageX_groupCountXaX_byXnameX_out_capXaX: [function({g}) { return g.V().has("age").groupCount("a").by("name").out().cap("a") }],
g_V_storeXa_nameX_out_capXaX: [function({g}) { return g.V().store("a").by("name").out().cap("a") }],
g_VX1X_storeXaX_byXnameX_out_storeXaX_byXnameX_name_capXaX: [function({g, vid1}) { return g.V(vid1).store("a").by("name").out().store("a").by("name").values("name").cap("a") }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 13900d6..5e705c6 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -104,6 +104,7 @@ world.gremlins = {
'g_V_coinX0X': [(lambda g:g.V().coin(float(0.0)))],
'g_withStrategiesXSeedStrategyX_V_coinX50X': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().coin(float(0.5)))],
'g_VX1X_outXcreatedX_inXcreatedX_cyclicPath': [(lambda g, vid1=None:g.V(vid1).out('created').in_('created').cyclicPath())],
+ 'g_VX1X_both_both_cyclicPath_byXageX': [(lambda g, vid1=None:g.V(vid1).both().both().cyclicPath().by('age'))],
'g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path': [(lambda g, vid1=None:g.V(vid1).out('created').in_('created').cyclicPath().path())],
'g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path': [(lambda g, vid1=None:g.V(vid1).as_('a').out('created').as_('b').in_('created').as_('c').cyclicPath().from_('a').to('b').path())],
'g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path': [(lambda g:g.inject(0).V().both().coalesce(__.has('name','marko').both(),__.constant(0)).cyclicPath().path())],
@@ -128,6 +129,9 @@ world.gremlins = {
'g_V_both_properties_dedup_count': [(lambda g:g.V().both().properties().dedup().count())],
'g_V_both_properties_properties_dedup_count': [(lambda g:g.V().both().properties().properties().dedup().count())],
'g_V_order_byXname_descX_barrier_dedup_age_name': [(lambda g:g.V().order().by('name',Order.desc).barrier().dedup().by('age').name)],
+ 'g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().order().by('name',Order.desc).barrier().dedup().by('age').name)],
+ 'g_V_both_dedup_age_name': [(lambda g:g.V().both().dedup().by('age').name)],
+ 'g_V_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name': [(lambda g:g.V().as_('a').both().as_('b').both().as_('c').dedup('a','b').by('age').select('a','b','c').by('name'))],
'g_V_drop': [(lambda g:g.addV().as_('a').addV().as_('b').addE('knows').to('a')), (lambda g:g.V().drop()), (lambda g:g.V()), (lambda g:g.E())],
'g_V_outE_drop': [(lambda g:g.addV().as_('a').addV().as_('b').addE('knows').to('a')), (lambda g:g.V().outE().drop()), (lambda g:g.V()), (lambda g:g.E())],
'g_V_properties_drop': [(lambda g:g.addV().property('name','bob').addV().property('name','alice')), (lambda g:g.V().properties().drop()), (lambda g:g.V()), (lambda g:g.V().properties())],
@@ -254,10 +258,12 @@ world.gremlins = {
'g_V_localXoutE_sampleX1X_byXweightXX': [(lambda g:g.V().local(__.outE().sample(1).by('weight')))],
'g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_sampleX2X_foldXunfold': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().group().by(T.label).by(__.bothE().weight.order().sample(2).fold()).unfold())],
'g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_fold_sampleXlocal_5XXunfold': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().group().by(T.label).by(__.bothE().weight.order().fold().sample(Scope.local,5)).unfold())],
+ 'g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().order().by(T.label,Order.desc).sample(1).by('age'))],
'g_VX1X_outXcreatedX_inXcreatedX_simplePath': [(lambda g, vid1=None:g.V(vid1).out('created').in_('created').simplePath())],
'g_V_repeatXboth_simplePathX_timesX3X_path': [(lambda g:g.V().repeat(__.both().simplePath()).times(3).path())],
'g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX': [(lambda g:g.V().as_('a').out().as_('b').out().as_('c').simplePath().by(T.label).from_('b').to('c').path().by('name'))],
'g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_simplePath_path': [(lambda g:g.inject(0).V().both().coalesce(__.has('name','marko').both(),__.constant(0)).simplePath().path())],
+ 'g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX': [(lambda g:g.V().both().as_('a').both().as_('b').simplePath().path().by('age').from_('a').to('b'))],
'g_V_valuesXnameX_order_tailXglobal_2X': [(lambda g:g.V().name.order().tail(Scope.global_,2))],
'g_V_valuesXnameX_order_tailX2X': [(lambda g:g.V().name.order().tail(2))],
'g_V_valuesXnameX_order_tail': [(lambda g:g.V().name.order().tail())],
@@ -296,6 +302,7 @@ world.gremlins = {
'g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX': [(lambda g:g.V().as_('a').outE('created').as_('b').inV().as_('c').in_('created').as_('d').where('a',P.lt('b').or_(P.gt('c')).and_(P.neq('d'))).by('age').by('weight').by(__.in_('created').age.min_()).select('a','c','d').by('name'))],
'g_VX1X_asXaX_out_hasXageX_whereXgtXaXX_byXageX_name': [(lambda g, vid1=None:g.V(vid1).as_('a').out().has('age').where(P.gt('a')).by('age').name)],
'g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name': [(lambda g, vid3=None:g.V(vid3).as_('a').in_().out().as_('b').where('a',P.eq('b')).by('age').name)],
+ 'g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name': [(lambda g, vid3=None:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V(vid3).as_('a').in_().out().as_('b').where('a',P.eq('b')).by('age').name)],
'g_V_coworker': [(lambda g, xx1=None:g.V().hasLabel('person').filter_(__.outE('created')).aggregate('p').as_('p1').name.as_('p1n').select('p').unfold().where(P.neq('p1')).as_('p2').name.as_('p2n').select('p2').out('created').choose(__.in_('created').where(P.eq('p1')),__.name,__.constant(xx1)).group().by(__.select('p1n')).by(__.group().by(__.select('p2n')).by(__.unfold().fold().project('numCoCreated','coCreated').by(__.count(Scope.local)).by())).unfold())],
'g_V_coworker_with_midV': [(lambda g:g.V().hasLabel('person').filter_(__.outE('created')).as_('p1').V().hasLabel('person').where(P.neq('p1')).filter_(__.outE('created')).as_('p2').map(__.out('created').where(__.in_('created').as_('p1')).name.fold()).group().by(__.select('p1').by('name')).by(__.group().by(__.select('p2').by('name')).by(__.project('numCoCreated','coCreated').by(__.count(Scope.local)).by())).unfold())],
'g_V_playlist_paths': [(lambda g:g.V().has('name','Bob_Dylan').in_('sungBy').order().by('name').as_('a').repeat(__.out().order().by('name').simplePath().from_('a')).until(__.out('writtenBy').has('name','Johnny_Cash'))[0:1].as_('b').repeat(__.out().order().by('name').as_('c').simplePath().from_('b').to('c')).until(__.out('sungBy').has('name','Grateful_Dead'))[0:1].path().from_('a').unfold().project('song','artists').by('name').by(__.coalesce(__.out('sungBy','writtenBy').dedup().name.o [...]
@@ -424,14 +431,20 @@ world.gremlins = {
'g_V_asXaX_outXcreatedX_asXbX_mathXb_plus_aX_byXinXcreatedX_countX_byXageX': [(lambda g:g.V().as_('a').out('created').as_('b').math('b + a').by(__.in_('created').count()).by('age'))],
'g_withSackX1X_injectX1X_repeatXsackXsumX_byXconstantX1XXX_timesX5X_emit_mathXsin__X_byXsackX': [(lambda g:g.withSack(1).inject(1).repeat(__.sack(Operator.sum_).by(__.constant(1))).times(5).emit().math('sin _').by(__.sack()))],
'g_V_projectXa_b_cX_byXbothE_weight_sumX_byXbothE_countX_byXnameX_order_byXmathXa_div_bX_descX_selectXcX': [(lambda g:g.V().project('a','b','c').by(__.bothE().weight.sum_()).by(__.bothE().count()).by('name').order().by(__.math('a / b'),Order.desc).select('c'))],
+ 'g_V_mathXit_plus_itXbyXageX': [(lambda g:g.V().math('_+_').by('age'))],
+ 'g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX': [(lambda g:g.V().valueMap().math('_+_').by(__.select('age').unfold()))],
'g_V_age_max': [(lambda g:g.V().age.max_())],
'g_V_foo_max': [(lambda g:g.V().foo.max_())],
'g_V_name_max': [(lambda g:g.V().name.max_())],
'g_V_age_fold_maxXlocalX': [(lambda g:g.V().age.fold().max_(Scope.local))],
'g_V_aggregateXaX_byXageX_capXaX_maxXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').max_(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_maxXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').max_(Scope.local))],
'g_V_aggregateXaX_byXageX_capXaX_unfold_max': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().max_())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().max_())],
'g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').max_(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').max_(Scope.local))],
'g_V_aggregateXaX_byXfooX_capXaX_unfold_max': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().max_())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().max_())],
'g_V_foo_fold_maxXlocalX': [(lambda g:g.V().foo.fold().max_(Scope.local))],
'g_V_name_fold_maxXlocalX': [(lambda g:g.V().name.fold().max_(Scope.local))],
'g_V_repeatXbothX_timesX5X_age_max': [(lambda g:g.V().repeat(__.both()).times(5).age.max_())],
@@ -442,9 +455,13 @@ world.gremlins = {
'g_V_foo_fold_meanXlocalX': [(lambda g:g.V().foo.fold().mean(Scope.local))],
'g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_meanX': [(lambda g:g.V().hasLabel('software').group().by('name').by(__.bothE().weight.mean()))],
'g_V_aggregateXaX_byXageX_meanXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').mean(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').mean(Scope.local))],
'g_V_aggregateXaX_byXageX_capXaX_unfold_mean': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().mean())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().mean())],
'g_V_aggregateXaX_byXfooX_meanXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').mean(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').mean(Scope.local))],
'g_V_aggregateXaX_byXfooX_capXaX_unfold_mean': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().mean())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().mean())],
'g_injectXnull_10_20_nullX_mean': [(lambda g, xx1=None,xx2=None:g.inject(None,xx1,xx2,None).mean())],
'g_injectXlistXnull_10_20_nullXX_meanXlocalX': [(lambda g, xx1=None:g.inject(xx1).mean(Scope.local))],
'g_V_age_min': [(lambda g:g.V().age.min_())],
@@ -452,9 +469,13 @@ world.gremlins = {
'g_V_name_min': [(lambda g:g.V().name.min_())],
'g_V_age_fold_minXlocalX': [(lambda g:g.V().age.fold().min_(Scope.local))],
'g_V_aggregateXaX_byXageX_capXaX_minXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').min_(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').min_(Scope.local))],
'g_V_aggregateXaX_byXageX_capXaX_unfold_min': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().min_())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().min_())],
'g_V_aggregateXaX_byXfooX_capXaX_minXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').min_(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').min_(Scope.local))],
'g_V_aggregateXaX_byXfooX_capXaX_unfold_min': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().min_())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().min_())],
'g_V_foo_fold_minXlocalX': [(lambda g:g.V().foo.fold().min_(Scope.local))],
'g_V_name_fold_minXlocalX': [(lambda g:g.V().name.fold().min_(Scope.local))],
'g_V_repeatXbothX_timesX5X_age_min': [(lambda g:g.V().repeat(__.both()).times(5).age.min_())],
@@ -479,11 +500,16 @@ world.gremlins = {
'g_V_both_hasLabelXpersonX_order_byXage_descX_name': [(lambda g:g.V().both().hasLabel('person').order().by('age',Order.desc).name)],
'g_V_order_byXoutE_count_descX': [(lambda g:g.V().order().by(__.outE().count(),Order.desc))],
'g_V_hasLabelXpersonX_order_byXageX': [(lambda g:g.V().hasLabel('person').order().by('age'))],
+ 'g_V_order_byXageX': [(lambda g:g.V().order().by('age'))],
+ 'g_V_fold_orderXlocalX_byXageX': [(lambda g:g.V().fold().order(Scope.local).by('age'))],
+ 'g_V_fold_orderXlocalX_byXage_descX': [(lambda g:g.V().fold().order(Scope.local).by('age',Order.desc))],
'g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX': [(lambda g:g.V().or_(__.hasLabel('person'),__.has('software','name','lop')).order().by('age'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().or_(__.hasLabel('person'),__.has('software','name','lop')).order().by('age'))],
'g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX': [(lambda g, l1=None,v1=None:g.V(v1).hasLabel('person').map(l1).order(Scope.local).by(Column.values,Order.desc).by(Column.keys,Order.asc))],
'g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX': [(lambda g:g.V().has('song','name','OH BOY').out('followedBy').out('followedBy').order().by('performances').by('songType',Order.desc).by('name'))],
'g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name': [(lambda g:g.V().hasLabel('song').order().by('performances',Order.desc).by('name')[110:120].name)],
'g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold': [(lambda g, vid1=None:g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.desc).unfold())],
+ 'g_VX1X_elementMap_orderXlocalX_byXkeys_ascXunfold': [(lambda g, vid1=None:g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.asc).unfold())],
'g_V_pageRank_hasXpageRankX': [(lambda g:g.V().pageRank().has('gremlin.pageRankVertexProgram.pageRank'))],
'g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX': [(lambda g:g.V().out('created').pageRank().with_('~tinkerpop.pageRank.edges',__.bothE()).with_('~tinkerpop.pageRank.propertyName','projectRank').with_('~tinkerpop.pageRank.times',0).valueMap('name','projectRank'))],
'g_V_pageRank_order_byXpageRank_descX_byXnameX_name': [(lambda g:g.V().pageRank().order().by('gremlin.pageRankVertexProgram.pageRank',Order.desc).by('name').name)],
@@ -501,6 +527,7 @@ world.gremlins = {
'g_VX1X_outEXcreatedX_inV_inE_outV_path': [(lambda g, vid1=None:g.V(vid1).outE('created').inV().inE().outV().path())],
'g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX': [(lambda g:g.V().as_('a').out().as_('b').out().as_('c').path().from_('b').to('c').by('name'))],
'g_VX1X_out_path_byXageX': [(lambda g, vid1=None:g.V(vid1).out().path().by('age'))],
+ 'g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX': [(lambda g, vid1=None:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V(vid1).out().path().by('age'))],
'g_injectX1_null_nullX_path': [(lambda g:g.inject(1,None,None).path())],
'g_injectX1_null_nullX_path_dedup': [(lambda g:g.inject(1,None,None).path().dedup())],
'g_V_peerPressure_hasXclusterX': [(lambda g:g.V().peerPressure().has('gremlin.peerPressureVertexProgram.cluster'))],
@@ -510,6 +537,7 @@ world.gremlins = {
'g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__descX_selectXaX': [(lambda g:g.V().out('created').project('a','b').by('name').by(__.in_('created').count()).order().by(__.select('b'),Order.desc).select('a'))],
'g_V_valueMap_projectXxX_byXselectXnameXX': [(lambda g:g.V().valueMap().project('x').by(__.select('name')))],
'g_V_projectXa_bX_byXinE_countX_byXageX': [(lambda g:g.V().project('a','b').by(__.inE().count()).by('age'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().project('a','b').by(__.inE().count()).by('age'))],
'g_V_hasXageX_propertiesXnameX': [(lambda g:g.V().has('age').properties('name').value())],
'g_V_hasXageX_propertiesXname_ageX_value': [(lambda g:g.V().has('age').properties('name','age').value())],
'g_V_hasXageX_propertiesXage_nameX_value': [(lambda g:g.V().has('age').properties('age','name').value())],
@@ -578,6 +606,8 @@ world.gremlins = {
'g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX': [(lambda g, eid11=None:g.E(eid11).properties('weight').as_('a').select('a').by(T.key))],
'g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX': [(lambda g, eid11=None:g.E(eid11).properties('weight').as_('a').select('a').by(T.value))],
'g_V_asXaX_selectXaX_byXageX': [(lambda g:g.V().as_('a').select('a').by('age'))],
+ 'g_V_asXa_nX_selectXa_nX_byXageX_byXnameX': [(lambda g:g.V().as_('a','n').select('a','n').by('age').by('name'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().as_('a').select('a').by('age'))],
'g_withSideEffectXk_nullX_injectXxX_selectXkX': [(lambda g:g.withSideEffect('k',None).inject('x').select('k'))],
'g_V_shortestPath': [(lambda g:g.V().identity().shortestPath())],
'g_V_both_dedup_shortestPath': [(lambda g:g.V().both().dedup().shortestPath())],
@@ -600,9 +630,13 @@ world.gremlins = {
'g_V_foo_fold_sumXlocalX': [(lambda g:g.V().foo.fold().sum_(Scope.local))],
'g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_sumX': [(lambda g:g.V().hasLabel('software').group().by('name').by(__.bothE().weight.sum_()))],
'g_V_aggregateXaX_byXageX_sumXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').sum_(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').sum_(Scope.local))],
'g_V_aggregateXaX_byXageX_capXaX_unfold_sum': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().sum_())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().sum_())],
'g_V_aggregateXaX_byXfooX_sumXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').sum_(Scope.local))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').sum_(Scope.local))],
'g_V_aggregateXaX_byXfooX_capXaX_unfold_sum': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().sum_())],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().sum_())],
'g_injectXnull_10_5_nullX_sum': [(lambda g, xx1=None,xx2=None:g.inject(None,xx1,xx2,None).sum_())],
'g_injectXlistXnull_10_5_nullXX_sumXlocalX': [(lambda g, xx1=None:g.inject(xx1).sum_(Scope.local))],
'g_V_localXoutE_foldX_unfold': [(lambda g:g.V().local(__.outE().fold()).unfold())],
@@ -621,6 +655,7 @@ world.gremlins = {
'g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX': [(lambda g:g.V().hasLabel('person').filter_(__.outE('created')).valueMap().with_('~tinkerpop.valueMap.tokens'))],
'g_VX1X_valueMapXname_locationX_byXunfoldX_by': [(lambda g, vid1=None:g.V(vid1).valueMap('name','location').by(__.unfold()).by())],
'g_V_valueMapXname_age_nullX': [(lambda g:g.V().valueMap('name','age',None))],
+ 'g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX': [(lambda g:g.V().valueMap('name','age').by(__.is_('x')).by(__.unfold()))],
'g_VXnullX': [(lambda g:g.V(None))],
'g_VXlistXnullXX': [(lambda g, xx1=None:g.V(xx1))],
'g_VX1_nullX': [(lambda g, vid1=None:g.V(vid1,None))],
@@ -682,17 +717,24 @@ world.gremlins = {
'g_V_aggregateXxX_byXnameX_capXxX': [(lambda g:g.V().aggregate('x').by('name').cap('x'))],
'g_V_out_aggregateXaX_path': [(lambda g:g.V().out().aggregate('a').path())],
'g_V_hasLabelXpersonX_aggregateXxX_byXageX_capXxX_asXyX_selectXyX': [(lambda g:g.V().hasLabel('person').aggregate('x').by('age').cap('x').as_('y').select('y'))],
+ 'g_V_aggregateXxX_byXageX_capXxX': [(lambda g:g.V().aggregate('x').by('age').cap('x'))],
+ 'g_V_aggregateXlocal_xX_byXageX_capXxX': [(lambda g:g.V().aggregate(Scope.local,'x').by('age').cap('x'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate(Scope.local,'x').by('age').cap('x'))],
'g_V_aggregateXlocal_a_nameX_out_capXaX': [(lambda g:g.V().aggregate(Scope.local,'a').by('name').out().cap('a'))],
'g_VX1X_aggregateXlocal_aX_byXnameX_out_aggregateXlocal_aX_byXnameX_name_capXaX': [(lambda g, vid1=None:g.V(vid1).aggregate(Scope.local,'a').by('name').out().aggregate(Scope.local,'a').by('name').name.cap('a'))],
'g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX': [(lambda g, xx1=None:g.withSideEffect('a',xx1).V().both().name.aggregate(Scope.local,'a').cap('a'))],
'g_V_aggregateXlocal_aX_byXoutEXcreatedX_countX_out_out_aggregateXlocal_aX_byXinEXcreatedX_weight_sumX': [(lambda g:g.V().aggregate(Scope.local,'a').by(__.outE('created').count()).out().out().aggregate(Scope.local,'a').by(__.inE('created').weight.sum_()).cap('a'))],
'g_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX': [(lambda g:g.V().aggregate('x').by(__.age.is_(P.gt(29))).cap('x'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('x').by(__.age.is_(P.gt(29))).cap('x'))],
'g_V_aggregateXxX_byXout_order_byXnameXX_capXxX': [(lambda g:g.V().aggregate('x').by(__.out().order().by('name')).cap('x'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('x').by(__.out().order().by('name')).cap('x'))],
'g_V_fail': [(lambda g:g.V().fail())],
'g_V_failXmsgX': [(lambda g:g.V().fail('msg'))],
'g_V_unionXout_failX': [(lambda g:g.V().union(__.out(),__.fail()))],
'g_V_group_byXnameX': [(lambda g:g.V().group().by('name'))],
'g_V_group_byXageX': [(lambda g:g.V().group().by('age'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_group_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().group().by('age'))],
+ 'g_V_group_byXnameX_byXageX': [(lambda g:g.V().group().by('name').by('age'))],
'g_V_group_byXnameX_by': [(lambda g:g.V().group().by('name').by())],
'g_V_groupXaX_byXnameX_capXaX': [(lambda g:g.V().group('a').by('name').cap('a'))],
'g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX': [(lambda g:g.V().has('lang').group('a').by('lang').by('name').out().cap('a'))],
@@ -716,6 +758,8 @@ world.gremlins = {
'g_V_group_byXlabelX_byXlabel_countX': [(lambda g:g.V().group().by(__.label()).by(__.label().count()))],
'g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX': [(lambda g:g.V().group('m').by(__.label()).by(__.label().count()).cap('m'))],
'g_V_outXcreatedX_groupCount_byXnameX': [(lambda g:g.V().out('created').groupCount().by('name'))],
+ 'g_V_groupCount_byXageX': [(lambda g:g.V().groupCount().by('age'))],
+ 'g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().groupCount().by('age'))],
'g_V_outXcreatedX_name_groupCount': [(lambda g:g.V().out('created').name.groupCount())],
'g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX': [(lambda g:g.V().out('created').groupCount('a').by('name').cap('a'))],
'g_V_outXcreatedX_name_groupCountXaX_capXaX': [(lambda g:g.V().out('created').name.groupCount('a').cap('a'))],
@@ -754,6 +798,7 @@ world.gremlins = {
'g_withBulkXfalseX_withSackX1_sumX_VX1X_localXoutEXknowsX_barrierXnormSackX_inVX_inXknowsX_barrier_sack': [(lambda g, vid1=None:g.withBulk(False).withSack(float(1.0),Operator.sum_).V(vid1).local(__.outE('knows').barrier(Barrier.normSack).inV()).in_('knows').barrier().sack())],
'g_withBulkXfalseX_withSackX1_sumX_V_out_barrier_sack': [(lambda g:g.withBulk(False).withSack(1,Operator.sum_).V().out().barrier().sack())],
'g_withSackX1_sumX_VX1X_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack': [(lambda g, vid1=None:g.withSack(float(1.0),Operator.sum_).V(vid1).local(__.out('knows').barrier(Barrier.normSack)).in_('knows').barrier().sack())],
+ 'g_V_sackXassignX_byXageX_sack': [(lambda g:g.V().sack(Operator.assign).by('age').sack())],
'g_V_hasXageX_groupCountXaX_byXnameX_out_capXaX': [(lambda g:g.V().has('age').groupCount('a').by('name').out().cap('a'))],
'g_V_storeXa_nameX_out_capXaX': [(lambda g:g.V().store('a').by('name').out().cap('a'))],
'g_VX1X_storeXaX_byXnameX_out_storeXaX_byXnameX_name_capXaX': [(lambda g, vid1=None:g.V(vid1).store('a').by('name').out().store('a').by('name').name.cap('a'))],
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
index a5df693..101acbb 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
@@ -363,7 +363,6 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
final String traversalSourceName = aliases.entrySet().iterator().next().getValue();
final TraversalSource g = graphManager.getTraversalSource(traversalSourceName);
- // todo: should session be grabbed here???
final Session session = getSession(context, msg);
// handle bytecode based graph operations like commit/rollback commands
@@ -504,6 +503,8 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
if (graph.features().graph().supportsTransactions()) {
if (TX_COMMIT.equals(bytecode) || TX_ROLLBACK.equals(bytecode)) {
final boolean commit = TX_COMMIT.equals(bytecode);
+
+ // there is no timeout on a commit/rollback
submitToGremlinExecutor(context, 0, session, new FutureTask<>(() -> {
try {
if (graph.tx().isOpen()) {
@@ -540,7 +541,8 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
}
context.writeAndFlush(specialResponseMsg.create());
} else {
- logger.warn(String.format("Exception processing a Traversal on request [%s].", msg.getRequestId()), ex);
+ logger.warn(String.format("Exception processing a Traversal on request [%s] to %s the transaction.",
+ msg.getRequestId(), commit ? "commit" : "rollback"), ex);
context.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
.statusMessage(ex.getMessage())
.statusAttributeException(ex).create());
diff --git a/gremlin-test/features/filter/CyclicPath.feature b/gremlin-test/features/filter/CyclicPath.feature
index 2de63ef..9deea88 100644
--- a/gremlin-test/features/filter/CyclicPath.feature
+++ b/gremlin-test/features/filter/CyclicPath.feature
@@ -30,6 +30,20 @@ Feature: Step - cyclicPath()
| result |
| v[marko] |
+ @GraphComputerVerificationReferenceOnly
+ Scenario: g_VX1X_both_both_cyclicPath_byXageX
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).both().both().cyclicPath().by('age')
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[marko] |
+
Scenario: g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path
Given the modern graph
And using the parameter vid1 defined as "v[marko].id"
diff --git a/gremlin-test/features/filter/Dedup.feature b/gremlin-test/features/filter/Dedup.feature
index 0cf9c21..c08f133 100644
--- a/gremlin-test/features/filter/Dedup.feature
+++ b/gremlin-test/features/filter/Dedup.feature
@@ -299,15 +299,29 @@ Feature: Step - dedup()
| result |
| d[21].l |
+ Scenario: g_V_order_byXname_descX_barrier_dedup_age_name
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().order().by("name",desc).barrier().dedup().by("age").values("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | vadas |
+ | peter |
+ | marko |
+ | josh |
+
# ensures that dedup() returns the first item encountered. the ordering supplied will put "ripple" in front of
# "lop" and make it the first to hit dedup() and as "age" is not a property of either of those only "ripple" will
# win. the barrier() is required to trick out FilterRankingStrategy which will optimize the traversal placing the
# dedup() prior to the order() and sorta ruin the test semantics
- Scenario: g_V_order_byXname_descX_barrier_dedup_age_name
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name
Given the modern graph
And the traversal of
"""
- g.V().order().by("name",desc).barrier().dedup().by("age").values("name")
+ g.withStrategies(ProductiveByStrategy).V().order().by("name",desc).barrier().dedup().by("age").values("name")
"""
When iterated to list
Then the result should be unordered
@@ -316,4 +330,32 @@ Feature: Step - dedup()
| ripple |
| peter |
| marko |
- | josh |
\ No newline at end of file
+ | josh |
+
+ Scenario: g_V_both_dedup_age_name
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().both().dedup().by("age").values("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | vadas |
+ | peter |
+ | marko |
+ | josh |
+
+ @GraphComputerVerificationReferenceOnly
+ Scenario: g_VX1X_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).as("a").both().as("b").both().as("c").dedup("a","b").by("age").select("a","b","c").by("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"a":"marko", "b":"vadas", "c":"marko"}] |
+ | m[{"a":"marko", "b":"josh", "c":"ripple"}] |
diff --git a/gremlin-test/features/filter/Sample.feature b/gremlin-test/features/filter/Sample.feature
index 44aa971..0319637 100644
--- a/gremlin-test/features/filter/Sample.feature
+++ b/gremlin-test/features/filter/Sample.feature
@@ -68,3 +68,14 @@ Feature: Step - sample()
| result |
| m[{"software":"l[d[0.2].d,d[0.4].d,d[0.4].d,d[1.0].d]"}] |
| m[{"person":"l[d[0.5].d,d[1.0].d,d[0.4].d,d[0.2].d,d[1.0].d]"}] |
+
+ Scenario: g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(new SeedStrategy(seed: 999999)).V().order().by(T.label, Order.desc).sample(1).by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[peter] |
\ No newline at end of file
diff --git a/gremlin-test/features/filter/SimplePath.feature b/gremlin-test/features/filter/SimplePath.feature
index 0020651..1555244 100644
--- a/gremlin-test/features/filter/SimplePath.feature
+++ b/gremlin-test/features/filter/SimplePath.feature
@@ -88,3 +88,20 @@ Feature: Step - simplePath()
| p[d[0].i,v[lop],v[marko],v[josh]] |
| p[d[0].i,v[josh],v[marko],v[lop]] |
| p[d[0].i,v[josh],v[marko],v[vadas]] |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().both().as('a').both().as('b').simplePath().path().by('age').from('a').to('b')
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | p[d[29].i,d[32].i] |
+ | p[d[29].i,d[27].i] |
+ | p[d[29].i,d[32].i] |
+ | p[d[32].i,d[29].i] |
+ | p[d[29].i,d[27].i] |
+ | p[d[32].i,d[29].i] |
diff --git a/gremlin-test/features/filter/Where.feature b/gremlin-test/features/filter/Where.feature
index 156d124..137ed5c 100644
--- a/gremlin-test/features/filter/Where.feature
+++ b/gremlin-test/features/filter/Where.feature
@@ -333,7 +333,6 @@ Feature: Step - where()
| result |
| josh |
- # comparison of null "age" values in where()
@GraphComputerVerificationReferenceOnly
Scenario: g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name
Given the modern graph
@@ -343,6 +342,18 @@ Feature: Step - where()
g.V(vid3).as("a").in().out().as("b").where("a", P.eq("b")).by("age").values("name")
"""
When iterated to list
+ Then the result should be empty
+
+ # comparison of null "age" values in where()
+ @GraphComputerVerificationReferenceOnly
+ Scenario: g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name
+ Given the modern graph
+ And using the parameter vid3 defined as "v[lop].id"
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V(vid3).as("a").in().out().as("b").where("a", P.eq("b")).by("age").values("name")
+ """
+ When iterated to list
Then the result should be unordered
| result |
| lop |
diff --git a/gremlin-test/features/map/Math.feature b/gremlin-test/features/map/Math.feature
index 768f37c..06cbd93 100644
--- a/gremlin-test/features/map/Math.feature
+++ b/gremlin-test/features/map/Math.feature
@@ -132,3 +132,31 @@ Feature: Step - math()
| vadas |
| lop |
| peter |
+
+ Scenario: g_V_mathXit_plus_itXbyXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().math("_+_").by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[64.0].d |
+ | d[58.0].d |
+ | d[54.0].d |
+ | d[70.0].d |
+
+ Scenario: g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().valueMap().math("_+_").by(__.select("age").unfold())
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[64.0].d |
+ | d[58.0].d |
+ | d[54.0].d |
+ | d[70.0].d |
\ No newline at end of file
diff --git a/gremlin-test/features/map/Max.feature b/gremlin-test/features/map/Max.feature
index 0d85cce..ef5a127 100644
--- a/gremlin-test/features/map/Max.feature
+++ b/gremlin-test/features/map/Max.feature
@@ -71,6 +71,17 @@ Feature: Step - max()
| result |
| d[35].i |
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_maxXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").max(Scope.local)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[35].i |
+
Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_max
Given the modern graph
And the traversal of
@@ -82,6 +93,17 @@ Feature: Step - max()
| result |
| d[35].i |
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().max()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[35].i |
+
Scenario: g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX
Given the modern graph
And the traversal of
@@ -89,6 +111,15 @@ Feature: Step - max()
g.V().aggregate("a").by("foo").cap("a").max(Scope.local)
"""
When iterated to list
+ Then the result should be empty
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").max(Scope.local)
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
@@ -100,6 +131,15 @@ Feature: Step - max()
g.V().aggregate("a").by("foo").cap("a").unfold().max()
"""
When iterated to list
+ Then the result should be empty
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().max()
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
diff --git a/gremlin-test/features/map/Mean.feature b/gremlin-test/features/map/Mean.feature
index cb1b2de..1b1de2f 100644
--- a/gremlin-test/features/map/Mean.feature
+++ b/gremlin-test/features/map/Mean.feature
@@ -82,6 +82,18 @@ Feature: Step - mean()
| d[30.75].d |
# null values are ignored in mean() which is similar to sum aggregation works in SQL
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").mean(Scope.local)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[30.75].d |
+
+ # null values are ignored in mean() which is similar to sum aggregation works in SQL
Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_mean
Given the modern graph
And the traversal of
@@ -93,6 +105,18 @@ Feature: Step - mean()
| result |
| d[30.75].d |
+ # null values are ignored in mean() which is similar to sum aggregation works in SQL
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().mean()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[30.75].d |
+
# if all values are null then the result is null
Scenario: g_V_aggregateXaX_byXfooX_meanXlocalX
Given the modern graph
@@ -101,6 +125,16 @@ Feature: Step - mean()
g.V().aggregate("a").by("foo").cap("a").mean(Scope.local)
"""
When iterated to list
+ Then the result should be empty
+
+ # if all values are null then the result is null
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").mean(Scope.local)
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
@@ -113,6 +147,16 @@ Feature: Step - mean()
g.V().aggregate("a").by("foo").cap("a").unfold().mean()
"""
When iterated to list
+ Then the result should be empty
+
+ # if all values are null then the result is null
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().mean()
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
diff --git a/gremlin-test/features/map/Min.feature b/gremlin-test/features/map/Min.feature
index 193e340..3146aa9 100644
--- a/gremlin-test/features/map/Min.feature
+++ b/gremlin-test/features/map/Min.feature
@@ -71,6 +71,17 @@ Feature: Step - min()
| result |
| d[27].i |
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").min(Scope.local)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[27].i |
+
Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_min
Given the modern graph
And the traversal of
@@ -82,6 +93,17 @@ Feature: Step - min()
| result |
| d[27].i |
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().min()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[27].i |
+
Scenario: g_V_aggregateXaX_byXfooX_capXaX_minXlocalX
Given the modern graph
And the traversal of
@@ -89,6 +111,15 @@ Feature: Step - min()
g.V().aggregate("a").by("foo").cap("a").min(Scope.local)
"""
When iterated to list
+ Then the result should be empty
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").min(Scope.local)
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
@@ -100,6 +131,15 @@ Feature: Step - min()
g.V().aggregate("a").by("foo").cap("a").unfold().min()
"""
When iterated to list
+ Then the result should be empty
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().min()
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
diff --git a/gremlin-test/features/map/Order.feature b/gremlin-test/features/map/Order.feature
index 7fb57b2..e1298e6 100644
--- a/gremlin-test/features/map/Order.feature
+++ b/gremlin-test/features/map/Order.feature
@@ -310,7 +310,49 @@ Feature: Step - order()
| v[josh] |
| v[peter] |
- # tests order().by() where a property isn't present to ensure null comes first
+ Scenario: g_V_order_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().order().by("age")
+ """
+ When iterated to list
+ Then the result should be ordered
+ | result |
+ | v[vadas] |
+ | v[marko] |
+ | v[josh] |
+ | v[peter] |
+
+ Scenario: g_V_fold_orderXlocalX_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().fold().order(local).by("age")
+ """
+ When iterated next
+ Then the result should be ordered
+ | result |
+ | v[vadas] |
+ | v[marko] |
+ | v[josh] |
+ | v[peter] |
+
+
+ Scenario: g_V_fold_orderXlocalX_byXage_descX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().fold().order(local).by("age", desc)
+ """
+ When iterated next
+ Then the result should be ordered
+ | result |
+ | v[peter] |
+ | v[josh] |
+ | v[marko] |
+ | v[vadas] |
+
Scenario: g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX
Given the modern graph
And the traversal of
@@ -320,6 +362,21 @@ Feature: Step - order()
When iterated to list
Then the result should be ordered
| result |
+ | v[vadas] |
+ | v[marko] |
+ | v[josh] |
+ | v[peter] |
+
+ # tests order().by() where a property isn't present to ensure null comes first
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().or(hasLabel("person"),has("software","name","lop")).order().by("age")
+ """
+ When iterated to list
+ Then the result should be ordered
+ | result |
| v[lop] |
| v[vadas] |
| v[marko] |
@@ -526,4 +583,19 @@ Feature: Step - order()
| m[{"name":"marko"}] |
| m[{"t[label]":"person"}] |
| m[{"t[id]":"v[marko].id"}] |
- | m[{"age":29}] |
\ No newline at end of file
+ | m[{"age":29}] |
+
+ Scenario: g_VX1X_elementMap_orderXlocalX_byXkeys_ascXunfold
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).elementMap().order(Scope.local).by(Column.keys, Order.asc).unfold()
+ """
+ When iterated to list
+ Then the result should be ordered
+ | result |
+ | m[{"age":29}] |
+ | m[{"t[id]":"v[marko].id"}] |
+ | m[{"t[label]":"person"}] |
+ | m[{"name":"marko"}] |
\ No newline at end of file
diff --git a/gremlin-test/features/map/Path.feature b/gremlin-test/features/map/Path.feature
index e4e9f2e..a5e5605 100644
--- a/gremlin-test/features/map/Path.feature
+++ b/gremlin-test/features/map/Path.feature
@@ -120,6 +120,20 @@ Feature: Step - path()
When iterated to list
Then the result should be unordered
| result |
+ | p[d[29].i,d[27].i] |
+ | p[d[29].i,d[32].i] |
+
+ @GraphComputerVerificationReferenceOnly
+ Scenario: g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V(vid1).out().path().by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
| p[d[29].i,null] |
| p[d[29].i,d[27].i] |
| p[d[29].i,d[32].i] |
diff --git a/gremlin-test/features/map/Project.feature b/gremlin-test/features/map/Project.feature
index bbcf9a4..645450f 100644
--- a/gremlin-test/features/map/Project.feature
+++ b/gremlin-test/features/map/Project.feature
@@ -82,6 +82,24 @@ Feature: Step - project()
When iterated to list
Then the result should be unordered
| result |
+ | m[{"a":"d[1].l"}] |
+ | m[{"a":"d[3].l"}] |
+ | m[{"a":"d[0].l", "b":"d[29].i"}] |
+ | m[{"a":"d[1].l", "b":"d[27].i"}] |
+ | m[{"a":"d[1].l", "b":"d[32].i"}] |
+ | m[{"a":"d[0].l", "b":"d[35].i"}] |
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().project("a", "b").
+ by(__.inE().count()).
+ by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
| m[{"a":"d[1].l", "b":null}] |
| m[{"a":"d[3].l", "b":null}] |
| m[{"a":"d[0].l", "b":"d[29].i"}] |
diff --git a/gremlin-test/features/map/Select.feature b/gremlin-test/features/map/Select.feature
index d334cbc..de599f2 100644
--- a/gremlin-test/features/map/Select.feature
+++ b/gremlin-test/features/map/Select.feature
@@ -819,8 +819,6 @@ Feature: Step - select()
| result |
| d[0.4].d |
- # ProductiveBy
- @GraphComputerVerificationReferenceOnly
Scenario: g_V_asXaX_selectXaX_byXageX
Given the modern graph
And the traversal of
@@ -832,6 +830,35 @@ Feature: Step - select()
| result |
| d[29].i |
| d[27].i |
+ | d[32].i |
+ | d[35].i |
+
+ Scenario: g_V_asXa_nX_selectXa_nX_byXageX_byXnameX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().as("a","n").select("a","n").by("age").by("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"a":"d[29].i","n":"marko"}] |
+ | m[{"a":"d[27].i","n":"vadas"}] |
+ | m[{"a":"d[32].i","n":"josh"}] |
+ | m[{"a":"d[35].i","n":"peter"}] |
+
+ @GraphComputerVerificationReferenceOnly
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().as("a").select("a").by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | d[27].i |
| null |
| d[32].i |
| null |
diff --git a/gremlin-test/features/map/Sum.feature b/gremlin-test/features/map/Sum.feature
index 44e59f7..cf1c3c9 100644
--- a/gremlin-test/features/map/Sum.feature
+++ b/gremlin-test/features/map/Sum.feature
@@ -82,6 +82,18 @@ Feature: Step - sum()
| d[123].i |
# null values are ignored in sum() which is similar to sum aggregation works in SQL
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").sum(Scope.local)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[123].i |
+
+ # null values are ignored in sum() which is similar to sum aggregation works in SQL
Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_sum
Given the modern graph
And the traversal of
@@ -93,7 +105,18 @@ Feature: Step - sum()
| result |
| d[123].l |
- # if all values are null then the result is null
+ # null values are ignored in sum() which is similar to sum aggregation works in SQL
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().sum()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[123].l |
+
Scenario: g_V_aggregateXaX_byXfooX_sumXlocalX
Given the modern graph
And the traversal of
@@ -101,6 +124,16 @@ Feature: Step - sum()
g.V().aggregate("a").by("foo").cap("a").sum(Scope.local)
"""
When iterated to list
+ Then the result should be empty
+
+ # if all values are null then the result is null
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").sum(Scope.local)
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
@@ -113,6 +146,16 @@ Feature: Step - sum()
g.V().aggregate("a").by("foo").cap("a").unfold().sum()
"""
When iterated to list
+ Then the result should be empty
+
+ # if all values are null then the result is null
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().sum()
+ """
+ When iterated to list
Then the result should be unordered
| result |
| null |
diff --git a/gremlin-test/features/map/ValueMap.feature b/gremlin-test/features/map/ValueMap.feature
index bedd50a..8a985d2 100644
--- a/gremlin-test/features/map/ValueMap.feature
+++ b/gremlin-test/features/map/ValueMap.feature
@@ -211,4 +211,20 @@ Feature: Step - valueMap()
| m[{"name": ["peter"], "age": [35]}] |
| m[{"name": ["vadas"], "age": [27]}] |
| m[{"name": ["lop"]}] |
- | m[{"name": ["ripple"]}] |
\ No newline at end of file
+ | m[{"name": ["ripple"]}] |
+
+ Scenario: g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().valueMap("name", "age").by(__.is("x")).by(__.unfold())
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"age": 29}] |
+ | m[{"age": 32}] |
+ | m[{"age": 35}] |
+ | m[{"age": 27}] |
+ | m[{}] |
+ | m[{}] |
\ No newline at end of file
diff --git a/gremlin-test/features/sideEffect/Aggregate.feature b/gremlin-test/features/sideEffect/Aggregate.feature
index 2f86692..b3de3ce 100644
--- a/gremlin-test/features/sideEffect/Aggregate.feature
+++ b/gremlin-test/features/sideEffect/Aggregate.feature
@@ -96,6 +96,50 @@ Feature: Step - aggregate()
| d[32].i |
| d[35].i |
+ Scenario: g_V_aggregateXxX_byXageX_capXxX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().aggregate("x").by("age").cap("x")
+ """
+ When iterated next
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | d[27].i |
+ | d[32].i |
+ | d[35].i |
+
+ Scenario: g_V_aggregateXlocal_xX_byXageX_capXxX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().aggregate(Scope.local, "x").by("age").cap("x")
+ """
+ When iterated next
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | d[27].i |
+ | d[32].i |
+ | d[35].i |
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate(Scope.local, "x").by("age").cap("x")
+ """
+ When iterated next
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | d[27].i |
+ | d[32].i |
+ | d[35].i |
+ | null |
+ | null |
+
Scenario: g_V_aggregateXlocal_a_nameX_out_capXaX
Given the modern graph
And the traversal of
@@ -177,13 +221,24 @@ Feature: Step - aggregate()
| result |
| d[32].i |
| d[35].i |
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x")
+ """
+ When iterated next
+ Then the result should be unordered
+ | result |
+ | d[32].i |
+ | d[35].i |
| null |
| null |
| null |
| null |
- # ProductiveBy
- @GraphComputerVerificationReferenceOnly
+ @GraphComputerVerificationStarGraphExceeded
Scenario: g_V_aggregateXxX_byXout_order_byXnameXX_capXxX
Given the modern graph
And the traversal of
@@ -196,6 +251,20 @@ Feature: Step - aggregate()
| v[josh] |
| v[lop] |
| v[lop] |
+
+ @GraphComputerVerificationReferenceOnly
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().aggregate("x").by(__.out().order().by("name")).cap("x")
+ """
+ When iterated next
+ Then the result should be unordered
+ | result |
+ | v[josh] |
+ | v[lop] |
+ | v[lop] |
| null |
| null |
| null |
\ No newline at end of file
diff --git a/gremlin-test/features/sideEffect/Group.feature b/gremlin-test/features/sideEffect/Group.feature
index e7c83a7..c33ab11 100644
--- a/gremlin-test/features/sideEffect/Group.feature
+++ b/gremlin-test/features/sideEffect/Group.feature
@@ -38,8 +38,30 @@ Feature: Step - group()
When iterated to list
Then the result should be unordered
| result |
+ | m[{"d[35].i":"l[v[peter]]", "d[27].i":"l[v[vadas]]", "d[32].i": "l[v[josh]]", "d[29].i":"l[v[marko]]"}] |
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_group_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().group().by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
| m[{"null":"l[v[lop],v[ripple]]", "d[35].i":"l[v[peter]]", "d[27].i":"l[v[vadas]]", "d[32].i": "l[v[josh]]", "d[29].i":"l[v[marko]]"}] |
+ Scenario: g_V_group_byXnameX_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().group().by("name").by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"ripple":[], "peter":"l[d[35].i]", "vadas":"l[d[27].i]", "josh": "l[d[32].i]", "lop":[], "marko":"l[d[29].i]"}] |
+
Scenario: g_V_group_byXnameX_by
Given the modern graph
And the traversal of
diff --git a/gremlin-test/features/sideEffect/GroupCount.feature b/gremlin-test/features/sideEffect/GroupCount.feature
index 98de286..3545c23 100644
--- a/gremlin-test/features/sideEffect/GroupCount.feature
+++ b/gremlin-test/features/sideEffect/GroupCount.feature
@@ -29,6 +29,28 @@ Feature: Step - groupCount()
| result |
| m[{"ripple":"d[1].l", "lop":"d[3].l"}] |
+ Scenario: g_V_groupCount_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().groupCount().by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"d[27].i":"d[1].l", "d[29].i":"d[1].l", "d[32].i":"d[1].l", "d[35].i":"d[1].l"}] |
+
+ Scenario: g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.withStrategies(ProductiveByStrategy).V().groupCount().by("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"null":"d[2].l", "d[27].i":"d[1].l", "d[29].i":"d[1].l", "d[32].i":"d[1].l", "d[35].i":"d[1].l"}] |
+
Scenario: g_V_outXcreatedX_name_groupCount
Given the modern graph
And the traversal of
diff --git a/gremlin-test/features/sideEffect/Sack.feature b/gremlin-test/features/sideEffect/Sack.feature
index 0ce1ad0..0e18d5c 100644
--- a/gremlin-test/features/sideEffect/Sack.feature
+++ b/gremlin-test/features/sideEffect/Sack.feature
@@ -98,6 +98,20 @@ Feature: Step - sack()
| d[1.0].m |
| d[1.0].m |
+ Scenario: g_V_sackXassignX_byXageX_sack
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().sack(assign).by("age").sack()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | d[27].i |
+ | d[32].i |
+ | d[35].i |
+
Scenario: g_withSackXBigInteger_TEN_powX1000X_assignX_V_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack
Given an unsupported test
Then nothing should happen because
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
index 35bb75e..161f787 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
@@ -150,11 +150,10 @@ public abstract class DedupTest extends AbstractGremlinProcessTest {
final Traversal<Vertex, String> traversal = get_g_V_order_byXname_descX_barrier_dedup_age_name();
printTraversalForm(traversal);
final List<String> names = traversal.toList();
- assertEquals(5, names.size());
+ assertEquals(4, names.size());
assertTrue(names.contains("marko"));
assertTrue(names.contains("vadas"));
assertTrue(names.contains("josh"));
- assertTrue(names.contains("ripple"));
assertTrue(names.contains("peter"));
assertFalse(traversal.hasNext());
}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
index dd02b59..0dc5d10 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
@@ -50,6 +50,8 @@ import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.not;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.or;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -413,7 +415,7 @@ public abstract class WhereTest extends AbstractGremlinProcessTest {
public void g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name() {
final Traversal<Vertex, String> traversal = get_g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name(convertToVertexId(graph, "lop"));
printTraversalForm(traversal);
- checkResults(Arrays.asList("lop", "lop", "lop", "ripple"), traversal);
+ assertThat(traversal.hasNext(), is(false));
}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java
index bb85fa2..1bfc79e 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java
@@ -105,7 +105,6 @@ public abstract class MaxTest extends AbstractGremlinProcessTest {
public void g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX() {
final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX();
printTraversalForm(traversal);
- assertNull(traversal.next());
assertFalse(traversal.hasNext());
}
@@ -114,7 +113,6 @@ public abstract class MaxTest extends AbstractGremlinProcessTest {
public void g_V_aggregateXaX_byXfooX_capXaX_unfold_max() {
final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_max();
printTraversalForm(traversal);
- assertNull(traversal.next());
assertFalse(traversal.hasNext());
}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java
index 0908646..a55918b 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java
@@ -91,7 +91,6 @@ public abstract class MeanTest extends AbstractGremlinProcessTest {
public void g_V_aggregateXaX_byXfooX_meanXlocalX() {
final Traversal<Vertex, Double> traversal = get_g_V_aggregateXaX_byXfooX_meanXlocalX();
printTraversalForm(traversal);
- assertNull(traversal.next());
assertFalse(traversal.hasNext());
}
@@ -100,7 +99,6 @@ public abstract class MeanTest extends AbstractGremlinProcessTest {
public void g_V_aggregateXaX_byXfooX_capXaX_unfold_mean() {
final Traversal<Vertex, Double> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_mean();
printTraversalForm(traversal);
- assertNull(traversal.next());
assertFalse(traversal.hasNext());
}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java
index 51c2e2a..383a833 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java
@@ -131,7 +131,6 @@ public abstract class MinTest extends AbstractGremlinProcessTest {
public void g_V_aggregateXaX_byXfooX_capXaX_minXlocalX() {
final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_minXlocalX();
printTraversalForm(traversal);
- assertNull(traversal.next());
assertFalse(traversal.hasNext());
}
@@ -140,7 +139,6 @@ public abstract class MinTest extends AbstractGremlinProcessTest {
public void g_V_aggregateXaX_byXfooX_capXaX_unfold_min() {
final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_min();
printTraversalForm(traversal);
- assertNull(traversal.next());
assertFalse(traversal.hasNext());
}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
index b41fe70..088273f 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
@@ -311,7 +311,7 @@ public abstract class OrderTest extends AbstractGremlinProcessTest {
public void g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX() {
final Traversal<Vertex, Vertex> traversal = get_g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX();
printTraversalForm(traversal);
- checkResults(Arrays.asList(convertToVertex(graph, "lop"), convertToVertex(graph, "vadas"), convertToVertex(graph, "marko"), convertToVertex(graph, "josh"), convertToVertex(graph, "peter")), traversal);
+ checkResults(Arrays.asList(convertToVertex(graph, "vadas"), convertToVertex(graph, "marko"), convertToVertex(graph, "josh"), convertToVertex(graph, "peter")), traversal);
}
@Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java
index d60b2cf..e4b0640 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java
@@ -95,8 +95,8 @@ public abstract class PathTest extends AbstractGremlinProcessTest {
assertTrue(path.get(1) == null || path.get(1).equals(27) || path.get(1).equals(32));
ages.add(path.get(1));
}
- assertEquals(3, counter);
- assertEquals(3, ages.size());
+ assertEquals(2, counter);
+ assertEquals(2, ages.size());
}
@Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
index c073eb1..11c49c2 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
@@ -27,9 +27,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.junit.Test;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
import static org.junit.Assert.assertEquals;
@@ -64,13 +68,32 @@ public abstract class ProjectTest extends AbstractGremlinProcessTest {
public void g_V_projectXa_bX_byXinE_countX_byXageX() {
final Traversal<Vertex, Map<String, Number>> traversal = get_g_V_projectXa_bX_byXinE_countX_byXageX();
printTraversalForm(traversal);
- checkResults(makeMapList(2,
- "a", 3l, "b", null,
- "a", 1L, "b", null,
- "a", 0L, "b", 29,
- "a", 1L, "b", 27,
- "a", 1L, "b", 32,
- "a", 0L, "b", 35), traversal);
+
+ final List<Map<String, Number>> a = new ArrayList<>();
+ a.add(new HashMap<String,Number>() {{
+ put("a", 3L);
+ }});
+ a.add(new HashMap<String,Number>() {{
+ put("a", 1L);
+ }});
+ a.add(new HashMap<String,Number>() {{
+ put("a", 0L);
+ put("b", 29);
+ }});
+ a.add(new HashMap<String,Number>() {{
+ put("a", 1L);
+ put("b", 27);
+ }});
+ a.add(new HashMap<String,Number>() {{
+ put("a", 1L);
+ put("b", 32);
+ }});
+ a.add(new HashMap<String,Number>() {{
+ put("a", 0L);
+ put("b", 35);
+ }});
+
+ checkResults(a, traversal);
}
@Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
index 4b450ca..dd8b7ca 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
@@ -898,7 +898,7 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
public void g_V_asXaX_selectXaX_byXageX() {
final Traversal<Vertex, Object> traversal = get_g_V_asXaX_selectXaX_byXageX();
printTraversalForm(traversal);
- checkResults(Arrays.asList(29, 27, null, 32, null, 35), traversal);
+ checkResults(Arrays.asList(29, 27, 32, 35), traversal);
}
@Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java
index 6d45fed..ccee6a8 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java
@@ -119,7 +119,6 @@ public abstract class SumTest extends AbstractGremlinProcessTest {
public void g_V_aggregateXaX_byXfooX_sumXlocalX() {
final Traversal<Vertex, Number> traversal = get_g_V_aggregateXaX_byXfooX_sumXlocalX();
printTraversalForm(traversal);
- assertNull(traversal.next());
assertFalse(traversal.hasNext());
}
@@ -127,8 +126,7 @@ public abstract class SumTest extends AbstractGremlinProcessTest {
@LoadGraphWith(MODERN)
public void g_V_aggregateXaX_byXfooX_capXaX_unfold_sum() {
final Traversal<Vertex, Number> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_sum();
- printTraversalForm(traversal);
- assertNull(traversal.next());
+ printTraversalForm(traversal);;
assertFalse(traversal.hasNext());
}
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java
index f3661e9..cf5eb31 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java
@@ -242,7 +242,7 @@ public abstract class AggregateTest extends AbstractGremlinProcessTest {
printTraversalForm(traversal);
final Collection<Integer> ages = traversal.next();
assertFalse(traversal.hasNext());
- assertThat(ages, containsInAnyOrder(null, null, null, null, 32, 35));
+ assertThat(ages, containsInAnyOrder(32, 35));
}
@Test
@@ -252,7 +252,7 @@ public abstract class AggregateTest extends AbstractGremlinProcessTest {
printTraversalForm(traversal);
final Collection<Vertex> ages = traversal.next();
assertFalse(traversal.hasNext());
- assertThat(ages, containsInAnyOrder(null, null, null, convertToVertex("lop"), convertToVertex("josh"), convertToVertex("lop")));
+ assertThat(ages, containsInAnyOrder(convertToVertex("lop"), convertToVertex("josh"), convertToVertex("lop")));
}
public static class Traversals extends AggregateTest {
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
index c7f86d7..897f2d2 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
@@ -123,7 +123,7 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
printTraversalForm(traversal);
final Map<Integer, Collection<Vertex>> map = traversal.next();
- assertEquals(5, map.size());
+ assertEquals(4, map.size());
map.forEach((key, values) -> {
if (null == key)
assertEquals(2, values.size());
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java
index a9a4b1b..72ee0f9 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java
@@ -52,6 +52,8 @@ public abstract class TreeTest extends AbstractGremlinProcessTest {
public abstract Traversal<Vertex, Tree> get_g_VX1X_out_out_tree_byXnameX(final Object v1Id);
+ public abstract Traversal<Vertex, Tree> get_g_V_out_tree_byXageX();
+
public abstract Traversal<Vertex, Tree> get_g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX(final Object v1Id);
public abstract Traversal<Vertex, Tree> get_g_V_out_out_out_tree();
@@ -66,6 +68,25 @@ public abstract class TreeTest extends AbstractGremlinProcessTest {
@Test
@LoadGraphWith(MODERN)
+ public void g_V_out_tree_byXageX() {
+ final Traversal<Vertex, Tree> traversal = get_g_V_out_tree_byXageX();
+ printTraversalForm(traversal);
+
+ final Tree tree = traversal.next();
+ assertFalse(traversal.hasNext());
+ assertEquals(3, tree.size());
+ assertTrue(tree.containsKey(29));
+ assertEquals(2, ((Map) tree.get(29)).size());
+ assertTrue(((Map) tree.get(29)).containsKey(32));
+ assertTrue(((Map) tree.get(29)).containsKey(27));
+ assertTrue(tree.containsKey(35));
+ assertEquals(0, ((Map) tree.get(35)).size());
+ assertTrue(tree.containsKey(32));
+ assertEquals(0, ((Map) tree.get(32)).size());
+ }
+
+ @Test
+ @LoadGraphWith(MODERN)
public void g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX() {
final Traversal<Vertex, Tree> traversal = get_g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX(convertToVertexId("marko"));
printTraversalForm(traversal);
@@ -153,6 +174,10 @@ public abstract class TreeTest extends AbstractGremlinProcessTest {
return g.V(v1Id).out().out().tree().by("name");
}
+ public Traversal<Vertex, Tree> get_g_V_out_tree_byXageX() {
+ return g.V().out().tree().by("age");
+ }
+
@Override
public Traversal<Vertex, Tree> get_g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX(final Object v1Id) {
return g.V(v1Id).out().out().tree("a").by("name").both().both().cap("a");