You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2017/04/18 11:23:18 UTC
[1/2] tinkerpop git commit: Renamed `RangeByIsCountStrategy` to
`CountStrategy`.
Repository: tinkerpop
Updated Branches:
refs/heads/master 043877282 -> 3d857cb2b
Renamed `RangeByIsCountStrategy` to `CountStrategy`.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/f08d44fc
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/f08d44fc
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/f08d44fc
Branch: refs/heads/master
Commit: f08d44fc5c8649658fd775289f0a49ec1816306d
Parents: 72b5186
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Thu Apr 13 21:21:36 2017 +0200
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Apr 13 21:21:36 2017 +0200
----------------------------------------------------------------------
CHANGELOG.asciidoc | 1 +
docs/src/reference/the-traversal.asciidoc | 2 +-
.../tinkerpop/gremlin/jsr223/CoreImports.java | 4 +-
.../process/traversal/TraversalStrategies.java | 4 +-
.../process/traversal/TraversalStrategy.java | 4 +-
.../strategy/optimization/CountStrategy.java | 191 +++++++++++++++++++
.../optimization/LazyBarrierStrategy.java | 2 +-
.../optimization/RangeByIsCountStrategy.java | 191 -------------------
.../structure/io/graphson/GraphSONModule.java | 10 +-
.../gremlin/structure/io/gryo/GryoVersion.java | 6 +-
.../tinkerpop/gremlin/util/CoreImports.java | 4 +-
.../optimization/CountStrategyTest.java | 113 +++++++++++
.../optimization/LazyBarrierStrategyTest.java | 4 +-
.../RangeByIsCountStrategyTest.java | 113 -----------
.../util/TraversalExplanationTest.java | 4 +-
.../jython/gremlin_python/process/strategies.py | 2 +-
.../process/traversal/step/map/ProfileTest.java | 4 +-
.../TinkerGraphNoStrategyComputerProvider.java | 4 +-
18 files changed, 332 insertions(+), 331 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index cedfda7..42479a2 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Renamed `RangeByIsCountStrategy` to `CountStrategy`.
* Added more specific typing to various `__` traversal steps. E.g. `<A,Vertex>out()` is `<Vertex,Vertex>out()`.
* Updated Docker build scripts to include Python dependencies (NOTE: users should remove any previously generated TinkerPop Docker images).
* Added "attachment requisite" `VertexProperty.element()` and `Property.element()` data in GraphSON serialization.
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 1303a22..ba94e8b 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -2797,7 +2797,7 @@ g.V().hasLabel('person'). <1>
<4> `InlineFilterStrategy` pulls out named predicates from `match()`-step to more easily allow provider strategies to use indices.
<5> `RepeatUnrollStrategy` will unroll loops and `IncidentToAdjacentStrategy` will turn `outE().inV()`-patterns into `out()`.
<6> `MatchPredicateStrategy` will pull in `where()`-steps so that they can be subjected to `match()`-steps runtime query optimizer.
-<7> `RangeByIsCountStrategy` will limit the traversal to only the number of traversers required for the `count().is(x)`-check.
+<7> `CountStrategy` will limit the traversal to only the number of traversers required for the `count().is(x)`-check.
<8> `PathRetractionStrategy` will remove paths from the traversers and increase the likelihood of bulking as path data is not required after `select('b')`.
<9> `AdjacentToIncidentStrategy` will turn `out()` into `outE()` to increase data access locality.
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index 5701e47..1296cfe 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -80,7 +80,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Lazy
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -228,7 +228,7 @@ public final class CoreImports {
CLASS_IMPORTS.add(MatchPredicateStrategy.class);
CLASS_IMPORTS.add(OrderLimitStrategy.class);
CLASS_IMPORTS.add(PathProcessorStrategy.class);
- CLASS_IMPORTS.add(RangeByIsCountStrategy.class);
+ CLASS_IMPORTS.add(CountStrategy.class);
CLASS_IMPORTS.add(ComputerVerificationStrategy.class);
CLASS_IMPORTS.add(LambdaRestrictionStrategy.class);
CLASS_IMPORTS.add(ReadOnlyStrategy.class);
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
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 63ae23f..972384c 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
@@ -33,7 +33,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Matc
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy;
@@ -211,7 +211,7 @@ public interface TraversalStrategies extends Serializable, Cloneable {
FilterRankingStrategy.instance(),
MatchPredicateStrategy.instance(),
RepeatUnrollStrategy.instance(),
- RangeByIsCountStrategy.instance(),
+ CountStrategy.instance(),
PathRetractionStrategy.instance(),
LazyBarrierStrategy.instance(),
ProfileStrategy.instance(),
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
index be9fc99..03c31ab 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
@@ -22,7 +22,7 @@ import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
import java.io.Serializable;
@@ -122,7 +122,7 @@ public interface TraversalStrategy<S extends TraversalStrategy> extends Serializ
/**
* Implemented by strategies that rewrite the traversal to be more efficient, but with the same semantics
- * (e.g. {@link RangeByIsCountStrategy}). During a re-write ONLY TinkerPop steps should be used.
+ * (e.g. {@link CountStrategy}). During a re-write ONLY TinkerPop steps should be used.
* For strategies that utilize provider specific steps, use {@link ProviderOptimizationStrategy}.
*/
public interface OptimizationStrategy extends TraversalStrategy<OptimizationStrategy> {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java
new file mode 100644
index 0000000..ecddd2c
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java
@@ -0,0 +1,191 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Compare;
+import org.apache.tinkerpop.gremlin.process.traversal.Contains;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.BiPredicate;
+
+/**
+ * This strategy optimizes any occurrence of {@link CountGlobalStep} followed by an {@link IsStep}. The idea is to limit
+ * the number of incoming elements in a way that it's enough for the {@link IsStep} to decide whether it evaluates
+ * {@code true} or {@code false}. If the traversal already contains a user supplied limit, the strategy won't
+ * modify it.
+ *
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ * @example <pre>
+ * __.outE().count().is(0) // is replaced by __.not(outE())
+ * __.outE().count().is(lt(3)) // is replaced by __.outE().limit(3).count().is(lt(3))
+ * __.outE().count().is(gt(3)) // is replaced by __.outE().limit(4).count().is(gt(3))
+ * </pre>
+ */
+public final class CountStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
+
+ private static final Map<BiPredicate, Long> RANGE_PREDICATES = new HashMap<BiPredicate, Long>() {{
+ put(Contains.within, 1L);
+ put(Contains.without, 0L);
+ }};
+ private static final Set<Compare> INCREASED_OFFSET_SCALAR_PREDICATES =
+ EnumSet.of(Compare.eq, Compare.neq, Compare.lte, Compare.gt);
+
+ private static final CountStrategy INSTANCE = new CountStrategy();
+
+ private CountStrategy() {
+ }
+
+ public static CountStrategy instance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public void apply(final Traversal.Admin<?, ?> traversal) {
+ final TraversalParent parent = traversal.getParent();
+ int size = traversal.getSteps().size();
+ Step prev = null;
+ for (int i = 0; i < size; i++) {
+ final Step curr = traversal.getSteps().get(i);
+ if (i < size - 1 && doStrategy(curr)) {
+ final IsStep isStep = (IsStep) traversal.getSteps().get(i + 1);
+ final P isStepPredicate = isStep.getPredicate();
+ Long highRange = null;
+ boolean useNotStep = false, dismissCountIs = false;
+ for (P p : isStepPredicate instanceof ConnectiveP ? ((ConnectiveP<?>) isStepPredicate).getPredicates() : Collections.singletonList(isStepPredicate)) {
+ final Object value = p.getValue();
+ final BiPredicate predicate = p.getBiPredicate();
+ if (value instanceof Number) {
+ final long highRangeOffset = INCREASED_OFFSET_SCALAR_PREDICATES.contains(predicate) ? 1L : 0L;
+ final Long highRangeCandidate = ((Number) value).longValue() + highRangeOffset;
+ final boolean update = highRange == null || highRangeCandidate > highRange;
+ if (update) {
+ if (parent instanceof EmptyStep) {
+ useNotStep = false;
+ } else {
+ if (parent instanceof RepeatStep) {
+ final RepeatStep repeatStep = (RepeatStep) parent;
+ dismissCountIs = useNotStep = Objects.equals(traversal, repeatStep.getUntilTraversal())
+ || Objects.equals(traversal, repeatStep.getEmitTraversal());
+ } else {
+ dismissCountIs = useNotStep = parent instanceof FilterStep || parent instanceof SideEffectStep;
+ }
+ }
+ highRange = highRangeCandidate;
+ useNotStep &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
+ && isStep.getNextStep() instanceof EmptyStep
+ && ((highRange <= 1L && predicate.equals(Compare.lt))
+ || (highRange == 1L && (predicate.equals(Compare.eq) || predicate.equals(Compare.lte))));
+ dismissCountIs &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
+ && isStep.getNextStep() instanceof EmptyStep
+ && (highRange == 1L && (predicate.equals(Compare.gt) || predicate.equals(Compare.gte)));
+ }
+ } else {
+ final Long highRangeOffset = RANGE_PREDICATES.get(predicate);
+ if (value instanceof Collection && highRangeOffset != null) {
+ final Object high = Collections.max((Collection) value);
+ if (high instanceof Number) {
+ final Long highRangeCandidate = ((Number) high).longValue() + highRangeOffset;
+ final boolean update = highRange == null || highRangeCandidate > highRange;
+ if (update) highRange = highRangeCandidate;
+ }
+ }
+ }
+ }
+ if (highRange != null) {
+ if (useNotStep || dismissCountIs) {
+ traversal.asAdmin().removeStep(isStep); // IsStep
+ traversal.asAdmin().removeStep(curr); // CountStep
+ size -= 2;
+ if (!dismissCountIs) {
+ if (traversal.getParent() instanceof FilterStep) {
+ final Step<?, ?> filterStep = parent.asStep();
+ final Traversal.Admin parentTraversal = filterStep.getTraversal();
+ final Step notStep = new NotStep<>(parentTraversal,
+ traversal.getSteps().isEmpty() ? __.identity() : traversal);
+ filterStep.getLabels().forEach(notStep::addLabel);
+ TraversalHelper.replaceStep(filterStep, notStep, parentTraversal);
+ } else {
+ final Traversal.Admin inner;
+ if (prev != null) {
+ inner = __.start().asAdmin();
+ for (; ; ) {
+ final Step pp = prev.getPreviousStep();
+ inner.addStep(0, prev);
+ if (pp instanceof EmptyStep || pp instanceof GraphStep ||
+ !(prev instanceof FilterStep || prev instanceof SideEffectStep)) break;
+ traversal.removeStep(prev);
+ prev = pp;
+ size--;
+ }
+ } else {
+ inner = __.identity().asAdmin();
+ }
+ if (prev != null)
+ TraversalHelper.replaceStep(prev, new NotStep<>(traversal, inner), traversal);
+ else
+ traversal.asAdmin().addStep(new NotStep<>(traversal, inner));
+ }
+ }
+ } else {
+ TraversalHelper.insertBeforeStep(new RangeGlobalStep<>(traversal, 0L, highRange), curr, traversal);
+ }
+ i++;
+ }
+ }
+ prev = curr;
+ }
+ }
+
+ private boolean doStrategy(final Step step) {
+ if (!(step instanceof CountGlobalStep) ||
+ !(step.getNextStep() instanceof IsStep) ||
+ step.getPreviousStep() instanceof RangeGlobalStep) // if a RangeStep was provided, assume that the user knows what he's doing
+ return false;
+
+ final Step parent = step.getTraversal().getParent().asStep();
+ return (parent instanceof FilterStep || parent.getLabels().isEmpty()) && // if the parent is labeled, then the count matters
+ !(parent.getNextStep() instanceof MatchStep.MatchEndStep && // if this is in a pattern match, then don't do it.
+ ((MatchStep.MatchEndStep) parent.getNextStep()).getMatchKey().isPresent());
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
index 29c04a7..9c8f931 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
@@ -47,7 +47,7 @@ public final class LazyBarrierStrategy extends AbstractTraversalStrategy<Travers
private final boolean IS_TESTING = Boolean.valueOf(System.getProperty("is.testing", "false"));
private static final LazyBarrierStrategy INSTANCE = new LazyBarrierStrategy();
private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>(Arrays.asList(
- RangeByIsCountStrategy.class,
+ CountStrategy.class,
PathRetractionStrategy.class,
IncidentToAdjacentStrategy.class,
AdjacentToIncidentStrategy.class,
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java
deleted file mode 100644
index b0cdb39..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Compare;
-import org.apache.tinkerpop.gremlin.process.traversal.Contains;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.BiPredicate;
-
-/**
- * This strategy optimizes any occurrence of {@link CountGlobalStep} followed by an {@link IsStep}. The idea is to limit
- * the number of incoming elements in a way that it's enough for the {@link IsStep} to decide whether it evaluates
- * {@code true} or {@code false}. If the traversal already contains a user supplied limit, the strategy won't
- * modify it.
- *
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @example <pre>
- * __.outE().count().is(0) // is replaced by __.not(outE())
- * __.outE().count().is(lt(3)) // is replaced by __.outE().limit(3).count().is(lt(3))
- * __.outE().count().is(gt(3)) // is replaced by __.outE().limit(4).count().is(gt(3))
- * </pre>
- */
-public final class RangeByIsCountStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
-
- private static final Map<BiPredicate, Long> RANGE_PREDICATES = new HashMap<BiPredicate, Long>() {{
- put(Contains.within, 1L);
- put(Contains.without, 0L);
- }};
- private static final Set<Compare> INCREASED_OFFSET_SCALAR_PREDICATES =
- EnumSet.of(Compare.eq, Compare.neq, Compare.lte, Compare.gt);
-
- private static final RangeByIsCountStrategy INSTANCE = new RangeByIsCountStrategy();
-
- private RangeByIsCountStrategy() {
- }
-
- public static RangeByIsCountStrategy instance() {
- return INSTANCE;
- }
-
- @Override
- public void apply(final Traversal.Admin<?, ?> traversal) {
- final TraversalParent parent = traversal.getParent();
- int size = traversal.getSteps().size();
- Step prev = null;
- for (int i = 0; i < size; i++) {
- final Step curr = traversal.getSteps().get(i);
- if (i < size - 1 && doStrategy(curr)) {
- final IsStep isStep = (IsStep) traversal.getSteps().get(i + 1);
- final P isStepPredicate = isStep.getPredicate();
- Long highRange = null;
- boolean useNotStep = false, dismissCountIs = false;
- for (P p : isStepPredicate instanceof ConnectiveP ? ((ConnectiveP<?>) isStepPredicate).getPredicates() : Collections.singletonList(isStepPredicate)) {
- final Object value = p.getValue();
- final BiPredicate predicate = p.getBiPredicate();
- if (value instanceof Number) {
- final long highRangeOffset = INCREASED_OFFSET_SCALAR_PREDICATES.contains(predicate) ? 1L : 0L;
- final Long highRangeCandidate = ((Number) value).longValue() + highRangeOffset;
- final boolean update = highRange == null || highRangeCandidate > highRange;
- if (update) {
- if (parent instanceof EmptyStep) {
- useNotStep = false;
- } else {
- if (parent instanceof RepeatStep) {
- final RepeatStep repeatStep = (RepeatStep) parent;
- dismissCountIs = useNotStep = Objects.equals(traversal, repeatStep.getUntilTraversal())
- || Objects.equals(traversal, repeatStep.getEmitTraversal());
- } else {
- dismissCountIs = useNotStep = parent instanceof FilterStep || parent instanceof SideEffectStep;
- }
- }
- highRange = highRangeCandidate;
- useNotStep &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
- && isStep.getNextStep() instanceof EmptyStep
- && ((highRange <= 1L && predicate.equals(Compare.lt))
- || (highRange == 1L && (predicate.equals(Compare.eq) || predicate.equals(Compare.lte))));
- dismissCountIs &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
- && isStep.getNextStep() instanceof EmptyStep
- && (highRange == 1L && (predicate.equals(Compare.gt) || predicate.equals(Compare.gte)));
- }
- } else {
- final Long highRangeOffset = RANGE_PREDICATES.get(predicate);
- if (value instanceof Collection && highRangeOffset != null) {
- final Object high = Collections.max((Collection) value);
- if (high instanceof Number) {
- final Long highRangeCandidate = ((Number) high).longValue() + highRangeOffset;
- final boolean update = highRange == null || highRangeCandidate > highRange;
- if (update) highRange = highRangeCandidate;
- }
- }
- }
- }
- if (highRange != null) {
- if (useNotStep || dismissCountIs) {
- traversal.asAdmin().removeStep(isStep); // IsStep
- traversal.asAdmin().removeStep(curr); // CountStep
- size -= 2;
- if (!dismissCountIs) {
- if (traversal.getParent() instanceof FilterStep) {
- final Step<?, ?> filterStep = parent.asStep();
- final Traversal.Admin parentTraversal = filterStep.getTraversal();
- final Step notStep = new NotStep<>(parentTraversal,
- traversal.getSteps().isEmpty() ? __.identity() : traversal);
- filterStep.getLabels().forEach(notStep::addLabel);
- TraversalHelper.replaceStep(filterStep, notStep, parentTraversal);
- } else {
- final Traversal.Admin inner;
- if (prev != null) {
- inner = __.start().asAdmin();
- for (; ; ) {
- final Step pp = prev.getPreviousStep();
- inner.addStep(0, prev);
- if (pp instanceof EmptyStep || pp instanceof GraphStep ||
- !(prev instanceof FilterStep || prev instanceof SideEffectStep)) break;
- traversal.removeStep(prev);
- prev = pp;
- size--;
- }
- } else {
- inner = __.identity().asAdmin();
- }
- if (prev != null)
- TraversalHelper.replaceStep(prev, new NotStep<>(traversal, inner), traversal);
- else
- traversal.asAdmin().addStep(new NotStep<>(traversal, inner));
- }
- }
- } else {
- TraversalHelper.insertBeforeStep(new RangeGlobalStep<>(traversal, 0L, highRange), curr, traversal);
- }
- i++;
- }
- }
- prev = curr;
- }
- }
-
- private boolean doStrategy(final Step step) {
- if (!(step instanceof CountGlobalStep) ||
- !(step.getNextStep() instanceof IsStep) ||
- step.getPreviousStep() instanceof RangeGlobalStep) // if a RangeStep was provided, assume that the user knows what he's doing
- return false;
-
- final Step parent = step.getTraversal().getParent().asStep();
- return (parent instanceof FilterStep || parent.getLabels().isEmpty()) && // if the parent is labeled, then the count matters
- !(parent.getNextStep() instanceof MatchStep.MatchEndStep && // if this is in a pattern match, then don't do it.
- ((MatchStep.MatchEndStep) parent.getNextStep()).getMatchKey().isPresent());
- }
-}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index 91df42a..019112b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -50,7 +50,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Matc
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
@@ -167,7 +167,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
OrderLimitStrategy.class,
PathProcessorStrategy.class,
PathRetractionStrategy.class,
- RangeByIsCountStrategy.class,
+ CountStrategy.class,
RepeatUnrollStrategy.class,
ComputerVerificationStrategy.class,
LambdaRestrictionStrategy.class,
@@ -275,7 +275,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
OrderLimitStrategy.class,
PathProcessorStrategy.class,
PathRetractionStrategy.class,
- RangeByIsCountStrategy.class,
+ CountStrategy.class,
RepeatUnrollStrategy.class,
ComputerVerificationStrategy.class,
LambdaRestrictionStrategy.class,
@@ -373,7 +373,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
OrderLimitStrategy.class,
PathProcessorStrategy.class,
PathRetractionStrategy.class,
- RangeByIsCountStrategy.class,
+ CountStrategy.class,
RepeatUnrollStrategy.class,
ComputerVerificationStrategy.class,
LambdaRestrictionStrategy.class,
@@ -481,7 +481,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
OrderLimitStrategy.class,
PathProcessorStrategy.class,
PathRetractionStrategy.class,
- RangeByIsCountStrategy.class,
+ CountStrategy.class,
RepeatUnrollStrategy.class,
ComputerVerificationStrategy.class,
LambdaRestrictionStrategy.class,
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index 54af562..f23095c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -61,7 +61,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Matc
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -305,7 +305,7 @@ public enum GryoVersion {
add(GryoTypeReg.of(OrderLimitStrategy.class, 152));
add(GryoTypeReg.of(PathProcessorStrategy.class, 153));
add(GryoTypeReg.of(PathRetractionStrategy.class, 154));
- add(GryoTypeReg.of(RangeByIsCountStrategy.class, 155));
+ add(GryoTypeReg.of(CountStrategy.class, 155));
add(GryoTypeReg.of(RepeatUnrollStrategy.class, 156));
add(GryoTypeReg.of(GraphFilterStrategy.class, 157));
add(GryoTypeReg.of(LambdaRestrictionStrategy.class, 158));
@@ -517,7 +517,7 @@ public enum GryoVersion {
add(GryoTypeReg.of(OrderLimitStrategy.class, 152));
add(GryoTypeReg.of(PathProcessorStrategy.class, 153));
add(GryoTypeReg.of(PathRetractionStrategy.class, 154));
- add(GryoTypeReg.of(RangeByIsCountStrategy.class, 155));
+ add(GryoTypeReg.of(CountStrategy.class, 155));
add(GryoTypeReg.of(RepeatUnrollStrategy.class, 156));
add(GryoTypeReg.of(GraphFilterStrategy.class, 157));
add(GryoTypeReg.of(LambdaRestrictionStrategy.class, 158));
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
index 597facf..1383fac 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
@@ -80,7 +80,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Lazy
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -191,7 +191,7 @@ public final class CoreImports {
CLASS_IMPORTS.add(MatchPredicateStrategy.class);
CLASS_IMPORTS.add(OrderLimitStrategy.class);
CLASS_IMPORTS.add(PathProcessorStrategy.class);
- CLASS_IMPORTS.add(RangeByIsCountStrategy.class);
+ CLASS_IMPORTS.add(CountStrategy.class);
CLASS_IMPORTS.add(ComputerVerificationStrategy.class);
CLASS_IMPORTS.add(LambdaRestrictionStrategy.class);
CLASS_IMPORTS.add(ReadOnlyStrategy.class);
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java
new file mode 100644
index 0000000..8408c07
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gte;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.inside;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lte;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.outside;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.within;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.without;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(Parameterized.class)
+public class CountStrategyTest {
+
+ @Parameterized.Parameter(value = 0)
+ public Traversal original;
+
+ @Parameterized.Parameter(value = 1)
+ public Traversal optimized;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable<Object[]> generateTestParameters() {
+
+ return Arrays.asList(new Traversal[][]{
+ {__.count().is(0), __.limit(1).count().is(0)},
+ {__.count().is(1), __.limit(2).count().is(1)},
+ {__.out().count().is(0), __.out().limit(1).count().is(0)},
+ {__.outE().count().is(lt(1)), __.outE().limit(1).count().is(lt(1))},
+ {__.both().count().is(lte(0)), __.both().limit(1).count().is(lte(0))},
+ {__.map(__.out().count().is(0)), __.map(__.out().limit(1).count().is(0))},
+ {__.map(__.outE().count().is(lt(1))), __.map(__.outE().limit(1).count().is(lt(1)))},
+ {__.map(__.both().count().is(lte(0))), __.map(__.both().limit(1).count().is(lte(0)))},
+ {__.filter(__.out().count().is(0)), __.not(__.out())},
+ {__.filter(__.outE().count().is(lt(1))), __.not(__.outE())},
+ {__.filter(__.both().count().is(lte(0))), __.not(__.both())},
+ {__.store("x").count().is(0).as("a"), __.store("x").limit(1).count().is(0).as("a")},
+ {__.out().count().as("a").is(0), __.out().limit(1).count().as("a").is(0)},
+ {__.out().count().is(neq(4)), __.out().limit(5).count().is(neq(4))},
+ {__.out().count().is(lte(3)), __.out().limit(4).count().is(lte(3))},
+ {__.out().count().is(lt(3)), __.out().limit(3).count().is(lt(3))},
+ {__.out().count().is(gt(2)), __.out().limit(3).count().is(gt(2))},
+ {__.out().count().is(gte(2)), __.out().limit(2).count().is(gte(2))},
+ {__.out().count().is(inside(2, 4)), __.out().limit(4).count().is(inside(2, 4))},
+ {__.out().count().is(outside(2, 4)), __.out().limit(5).count().is(outside(2, 4))},
+ {__.out().count().is(within(2, 6, 4)), __.out().limit(7).count().is(within(2, 6, 4))},
+ {__.out().count().is(without(2, 6, 4)), __.out().limit(6).count().is(without(2, 6, 4))},
+ {__.map(__.count().is(0)), __.map(__.limit(1).count().is(0))},
+ {__.flatMap(__.count().is(0)), __.flatMap(__.limit(1).count().is(0))},
+ {__.flatMap(__.count().is(0)).as("a"), __.flatMap(__.count().is(0)).as("a")},
+ {__.filter(__.count().is(0)).as("a"), __.not(__.identity()).as("a")},
+ {__.filter(__.count().is(0)), __.not(__.identity())},
+ {__.sideEffect(__.count().is(0)), __.sideEffect(__.not(__.identity()))},
+ {__.branch(__.count().is(0)), __.branch(__.limit(1).count().is(0))},
+ {__.count().is(0).store("x"), __.limit(1).count().is(0).store("x")},
+ {__.repeat(__.out()).until(__.outE().count().is(0)), __.repeat(__.out()).until(__.not(__.outE()))},
+ {__.repeat(__.out()).emit(__.outE().count().is(0)), __.repeat(__.out()).emit(__.not(__.outE()))},
+ {__.where(__.outE().hasLabel("created").count().is(0)), __.not(__.outE().hasLabel("created"))},
+ {__.where(__.out().outE().hasLabel("created").count().is(0)), __.not(__.out().outE().hasLabel("created"))},
+ {__.where(__.out().outE().hasLabel("created").count().is(0).store("x")), __.where(__.out().outE().hasLabel("created").limit(1).count().is(0).store("x"))},
+ {__.filter(__.bothE().count().is(gt(0))), __.filter(__.bothE())},
+ {__.filter(__.bothE().count().is(gte(1))), __.filter(__.bothE())},
+ {__.filter(__.bothE().count().is(gt(1))), __.filter(__.bothE().limit(2).count().is(gt(1)))},
+ {__.filter(__.bothE().count().is(gte(2))), __.filter(__.bothE().limit(2).count().is(gte(2)))},
+ });
+ }
+
+ void applyCountStrategy(final Traversal traversal) {
+ final TraversalStrategies strategies = new DefaultTraversalStrategies();
+ strategies.addStrategies(CountStrategy.instance());
+ traversal.asAdmin().setStrategies(strategies);
+ traversal.asAdmin().applyStrategies();
+ }
+
+ @Test
+ public void doTest() {
+ applyCountStrategy(original);
+ assertEquals(optimized, original);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
index f67abd1..b2bbd94 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
@@ -76,8 +76,8 @@ public class LazyBarrierStrategyTest {
{__.out().out().count(), __.out().out().count(), Collections.emptyList()},
{__.out().out().out().count(), __.out().out().barrier(LAZY_SIZE).out().count(), Collections.emptyList()},
{__.out().out().out().out().count(), __.out().out().barrier(LAZY_SIZE).out().barrier(LAZY_SIZE).out().count(), Collections.emptyList()},
- {__.out().out().out().count(), __.out().out().barrier(LAZY_SIZE).outE().count(), Arrays.asList(RangeByIsCountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
- {__.out().out().out().count().is(P.gt(10)), __.out().out().barrier(LAZY_SIZE).outE().limit(11).count().is(P.gt(10)), Arrays.asList(RangeByIsCountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
+ {__.out().out().out().count(), __.out().out().barrier(LAZY_SIZE).outE().count(), Arrays.asList(CountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
+ {__.out().out().out().count().is(P.gt(10)), __.out().out().barrier(LAZY_SIZE).outE().limit(11).count().is(P.gt(10)), Arrays.asList(CountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
{__.outE().inV().outE().inV().outE().inV().groupCount(), __.outE().inV().outE().inV().barrier(LAZY_SIZE).outE().inV().groupCount(), Collections.emptyList()},
{__.outE().inV().outE().inV().outE().inV().groupCount(), __.out().out().barrier(LAZY_SIZE).out().groupCount(), Collections.singletonList(IncidentToAdjacentStrategy.instance())},
{__.out().out().has("age", 32).out().count(), __.out().out().barrier(LAZY_SIZE).has("age", 32).out().count(), Collections.emptyList()},
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java
deleted file mode 100644
index 9f3b97d..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.util.Arrays;
-
-import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.gte;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.inside;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.lte;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.outside;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.within;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.without;
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@RunWith(Parameterized.class)
-public class RangeByIsCountStrategyTest {
-
- @Parameterized.Parameter(value = 0)
- public Traversal original;
-
- @Parameterized.Parameter(value = 1)
- public Traversal optimized;
-
- @Parameterized.Parameters(name = "{0}")
- public static Iterable<Object[]> generateTestParameters() {
-
- return Arrays.asList(new Traversal[][]{
- {__.count().is(0), __.limit(1).count().is(0)},
- {__.count().is(1), __.limit(2).count().is(1)},
- {__.out().count().is(0), __.out().limit(1).count().is(0)},
- {__.outE().count().is(lt(1)), __.outE().limit(1).count().is(lt(1))},
- {__.both().count().is(lte(0)), __.both().limit(1).count().is(lte(0))},
- {__.map(__.out().count().is(0)), __.map(__.out().limit(1).count().is(0))},
- {__.map(__.outE().count().is(lt(1))), __.map(__.outE().limit(1).count().is(lt(1)))},
- {__.map(__.both().count().is(lte(0))), __.map(__.both().limit(1).count().is(lte(0)))},
- {__.filter(__.out().count().is(0)), __.not(__.out())},
- {__.filter(__.outE().count().is(lt(1))), __.not(__.outE())},
- {__.filter(__.both().count().is(lte(0))), __.not(__.both())},
- {__.store("x").count().is(0).as("a"), __.store("x").limit(1).count().is(0).as("a")},
- {__.out().count().as("a").is(0), __.out().limit(1).count().as("a").is(0)},
- {__.out().count().is(neq(4)), __.out().limit(5).count().is(neq(4))},
- {__.out().count().is(lte(3)), __.out().limit(4).count().is(lte(3))},
- {__.out().count().is(lt(3)), __.out().limit(3).count().is(lt(3))},
- {__.out().count().is(gt(2)), __.out().limit(3).count().is(gt(2))},
- {__.out().count().is(gte(2)), __.out().limit(2).count().is(gte(2))},
- {__.out().count().is(inside(2, 4)), __.out().limit(4).count().is(inside(2, 4))},
- {__.out().count().is(outside(2, 4)), __.out().limit(5).count().is(outside(2, 4))},
- {__.out().count().is(within(2, 6, 4)), __.out().limit(7).count().is(within(2, 6, 4))},
- {__.out().count().is(without(2, 6, 4)), __.out().limit(6).count().is(without(2, 6, 4))},
- {__.map(__.count().is(0)), __.map(__.limit(1).count().is(0))},
- {__.flatMap(__.count().is(0)), __.flatMap(__.limit(1).count().is(0))},
- {__.flatMap(__.count().is(0)).as("a"), __.flatMap(__.count().is(0)).as("a")},
- {__.filter(__.count().is(0)).as("a"), __.not(__.identity()).as("a")},
- {__.filter(__.count().is(0)), __.not(__.identity())},
- {__.sideEffect(__.count().is(0)), __.sideEffect(__.not(__.identity()))},
- {__.branch(__.count().is(0)), __.branch(__.limit(1).count().is(0))},
- {__.count().is(0).store("x"), __.limit(1).count().is(0).store("x")},
- {__.repeat(__.out()).until(__.outE().count().is(0)), __.repeat(__.out()).until(__.not(__.outE()))},
- {__.repeat(__.out()).emit(__.outE().count().is(0)), __.repeat(__.out()).emit(__.not(__.outE()))},
- {__.where(__.outE().hasLabel("created").count().is(0)), __.not(__.outE().hasLabel("created"))},
- {__.where(__.out().outE().hasLabel("created").count().is(0)), __.not(__.out().outE().hasLabel("created"))},
- {__.where(__.out().outE().hasLabel("created").count().is(0).store("x")), __.where(__.out().outE().hasLabel("created").limit(1).count().is(0).store("x"))},
- {__.filter(__.bothE().count().is(gt(0))), __.filter(__.bothE())},
- {__.filter(__.bothE().count().is(gte(1))), __.filter(__.bothE())},
- {__.filter(__.bothE().count().is(gt(1))), __.filter(__.bothE().limit(2).count().is(gt(1)))},
- {__.filter(__.bothE().count().is(gte(2))), __.filter(__.bothE().limit(2).count().is(gte(2)))},
- });
- }
-
- void applyRangeByIsCountStrategy(final Traversal traversal) {
- final TraversalStrategies strategies = new DefaultTraversalStrategies();
- strategies.addStrategies(RangeByIsCountStrategy.instance());
- traversal.asAdmin().setStrategies(strategies);
- traversal.asAdmin().applyStrategies();
- }
-
- @Test
- public void doTest() {
- applyRangeByIsCountStrategy(original);
- assertEquals(optimized, original);
- }
-}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
index 3040fe8..c7eab92 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
@@ -117,7 +117,7 @@ public class TraversalExplanationTest {
found++;
if (line.contains("AdjacentToIncidentStrategy") && line.contains("[VertexStep(BOTH,edge)"))
found++;
- if (line.contains("RangeByIsCountStrategy") && line.contains("RangeGlobalStep(0,3)"))
+ if (line.contains("CountStrategy") && line.contains("RangeGlobalStep(0,3)"))
found++;
}
assertEquals(4, found);
@@ -130,7 +130,7 @@ public class TraversalExplanationTest {
found++;
if (line.contains("AdjacentToIncidentStrategy") && line.contains("[VertexStep(BOTH,edge)"))
found++;
- if (line.contains("RangeByIsCountStrategy") && line.contains("RangeGlobalStep(0,3)"))
+ if (line.contains("CountStrategy") && line.contains("RangeGlobalStep(0,3)"))
found++;
}
assertEquals(4, found);
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
index 8eb7fbd..f5ba9fb 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
@@ -154,7 +154,7 @@ class PathRetractionStrategy(TraversalStrategy):
TraversalStrategy.__init__(self)
-class RangeByIsCountStrategy(TraversalStrategy):
+class CountStrategy(TraversalStrategy):
def __init__(self):
TraversalStrategy.__init__(self)
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
index 1af6ba3..06afc1f 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
@@ -32,7 +32,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.Profiling;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
@@ -299,7 +299,7 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
assertEquals(1, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
assertEquals(1, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
- if (traversal.asAdmin().getStrategies().toList().stream().anyMatch(s -> s instanceof RangeByIsCountStrategy)) {
+ if (traversal.asAdmin().getStrategies().toList().stream().anyMatch(s -> s instanceof CountStrategy)) {
assertEquals("Metrics 1 should have 4 nested metrics.", 4, metrics.getNested().size());
} else {
assertEquals("Metrics 1 should have 3 nested metrics.", 3, metrics.getNested().size());
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
index 50ba5d4..ded754d 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
@@ -25,7 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.Connec
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SideEffectStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
@@ -41,7 +41,7 @@ import java.util.stream.Collectors;
public class TinkerGraphNoStrategyComputerProvider extends TinkerGraphComputerProvider {
private static final HashSet<Class<? extends TraversalStrategy>> REQUIRED_STRATEGIES = new HashSet<>(Arrays.asList(
- RangeByIsCountStrategy.class,
+ CountStrategy.class,
ComputerVerificationStrategy.class,
ProfileStrategy.class,
FilterRankingStrategy.class,
[2/2] tinkerpop git commit: Merge branch 'TINKERPOP-1313'
Posted by dk...@apache.org.
Merge branch 'TINKERPOP-1313'
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/3d857cb2
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/3d857cb2
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/3d857cb2
Branch: refs/heads/master
Commit: 3d857cb2b059426234a1b13c4ca0fbab369efcc3
Parents: 0438772 f08d44f
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Tue Apr 18 13:22:46 2017 +0200
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Tue Apr 18 13:22:46 2017 +0200
----------------------------------------------------------------------
CHANGELOG.asciidoc | 1 +
docs/src/reference/the-traversal.asciidoc | 2 +-
.../tinkerpop/gremlin/jsr223/CoreImports.java | 4 +-
.../process/traversal/TraversalStrategies.java | 4 +-
.../process/traversal/TraversalStrategy.java | 4 +-
.../strategy/optimization/CountStrategy.java | 191 +++++++++++++++++++
.../optimization/LazyBarrierStrategy.java | 2 +-
.../optimization/RangeByIsCountStrategy.java | 191 -------------------
.../structure/io/graphson/GraphSONModule.java | 10 +-
.../gremlin/structure/io/gryo/GryoVersion.java | 6 +-
.../tinkerpop/gremlin/util/CoreImports.java | 4 +-
.../optimization/CountStrategyTest.java | 113 +++++++++++
.../optimization/LazyBarrierStrategyTest.java | 4 +-
.../RangeByIsCountStrategyTest.java | 113 -----------
.../util/TraversalExplanationTest.java | 4 +-
.../jython/gremlin_python/process/strategies.py | 2 +-
.../process/traversal/step/map/ProfileTest.java | 4 +-
.../TinkerGraphNoStrategyComputerProvider.java | 4 +-
18 files changed, 332 insertions(+), 331 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3d857cb2/CHANGELOG.asciidoc
----------------------------------------------------------------------