Skip to content

Commit cb6e62e

Browse files
committed
Merge branch '3.8-dev'
2 parents 54173c8 + bd9be2c commit cb6e62e

11 files changed

Lines changed: 53 additions & 1 deletion

File tree

CHANGELOG.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ This release also includes changes from <<release-3-7-XXX, 3.7.XXX>>.
119119
* Deprecated `ProfilingAware.prepareForProfiling` method preferring to simply `resetBarrierFromValueTraversal` from the `Grouping` interface after strategy application.
120120
* Added missing strategies in `gremlin-go`, updated certain strategies to take varargs and updated `GoTranslatorVisitor` for corresponding translations.
121121
* Fixed `BigInt` and `BigDecimal` parsing in `gremlin-go` cucumber test suite, fixed `UnscaledValue` type in `BigDecimal` struct and added `ParseBigDecimal` method.
122+
* Added validation to `groupCount()` to prevent an invalid usage of multiple `by()` modulators.
122123
123124
== TinkerPop 3.7.0 (Gremfir Master of the Pan Flute)
124125

docs/src/upgrade/release-3.8.x.asciidoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@ gremlin> g.V().has("person","name",P.within("vadas","peter")).group().by().by(__
210210
211211
See: link:https://issues.apache.org/jira/browse/TINKERPOP-2971[TINKERPOP-2971]
212212
213+
==== groupCount() By Modulation Semantics
214+
215+
The `groupCount()` step has been changed to throw an error if multiple `by()` modulators are applied. The previous
216+
behavior would ignore previous `by()` modulators and apply the last one, which was not intuitive.
217+
218+
See: link:https://issues.apache.org/jira/browse/TINKERPOP-3121[TINKERPOP-3121]
219+
213220
=== Upgrading for Providers
214221
215222
==== Graph System Providers

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public Set<TraverserRequirement> getRequirements() {
7575

7676
@Override
7777
public void modulateBy(final Traversal.Admin<?, ?> keyTraversal) throws UnsupportedOperationException {
78+
if (this.keyTraversal != null) {
79+
throw new IllegalStateException("GroupCount step can only have one by modulator");
80+
}
7881
this.keyTraversal = this.integrateChild(keyTraversal);
7982
}
8083

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ public int hashCode() {
104104

105105
@Override
106106
public void modulateBy(final Traversal.Admin<?, ?> keyTraversal) throws UnsupportedOperationException {
107+
if (this.keyTraversal != null) {
108+
throw new IllegalStateException("GroupCount step can only have one by modulator");
109+
}
107110
this.keyTraversal = this.integrateChild(keyTraversal);
108111
}
109112

gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStepTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.util.Arrays;
2727
import java.util.List;
28+
import org.junit.Test;
2829

2930
/**
3031
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -39,4 +40,9 @@ protected List<Traversal> getTraversals() {
3940
__.groupCount().by("age")
4041
);
4142
}
43+
44+
@Test(expected = IllegalStateException.class)
45+
public void shouldThrowForMultipleByModulators() {
46+
__.groupCount().by("name").by("age");
47+
}
4248
}

gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStepTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import java.util.Arrays;
2626
import java.util.List;
27+
import org.junit.Test;
2728

2829
/**
2930
* @author Daniel Kuppitz (http://gremlin.guru)
@@ -41,4 +42,9 @@ protected List<Traversal> getTraversals() {
4142
__.groupCount("y").by("age")
4243
);
4344
}
45+
46+
@Test(expected = IllegalStateException.class)
47+
public void shouldThrowForMultipleByModulators() {
48+
__.groupCount("x").by("name").by("age");
49+
}
4450
}

gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,8 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
16121612
{"g_V_groupCount_byXbothE_countX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().GroupCount<object>().By(__.BothE().Count())}},
16131613
{"g_V_both_groupCountXaX_out_capXaX_selectXkeysX_unfold_both_groupCountXaX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().GroupCount("a").Out().Cap<object>("a").Select<object>(Column.Keys).Unfold<object>().Both().GroupCount("a").Cap<object>("a")}},
16141614
{"g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("person", "name", "marko").Both("knows").GroupCount<object>().By(__.Values<object>("name").Fold())}},
1615+
{"g_V_outXcreatedX_groupCount_byXnameX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").GroupCount<object>().By("name").By("age")}},
1616+
{"g_V_outXcreatedX_groupCountXxX_byXnameX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").GroupCount("x").By("name").By("age")}},
16151617
{"g_VX1X_out_injectXv2X_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().Inject((Vertex) p["v2"]).Values<object>("name")}},
16161618
{"g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>()}, // skipping as it contains a lambda
16171619
{"g_VX1X_injectXg_VX4XX_out_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Inject((Vertex) p["v2"]).Out().Values<object>("name")}},

gremlin-go/driver/cucumber/gremlin.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
15851585
"g_V_groupCount_byXbothE_countX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().GroupCount().By(gremlingo.T__.BothE().Count())}},
15861586
"g_V_both_groupCountXaX_out_capXaX_selectXkeysX_unfold_both_groupCountXaX_capXaX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Both().GroupCount("a").Out().Cap("a").Select(gremlingo.Column.Keys).Unfold().Both().GroupCount("a").Cap("a")}},
15871587
"g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Both("knows").GroupCount().By(gremlingo.T__.Values("name").Fold())}},
1588+
"g_V_outXcreatedX_groupCount_byXnameX_byXageX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out("created").GroupCount().By("name").By("age")}},
1589+
"g_V_outXcreatedX_groupCountXxX_byXnameX_byXageX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out("created").GroupCount("x").By("name").By("age")}},
15881590
"g_VX1X_out_injectXv2X_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out().Inject(p["v2"]).Values("name")}},
15891591
"g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return nil}}, // skipping as it contains a lambda
15901592
"g_VX1X_injectXg_VX4XX_out_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Inject(p["v2"]).Out().Values("name")}},

gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gremlin-python/src/main/python/radish/gremlin.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,8 @@
16451645
'g_V_groupCount_byXbothE_countX': [(lambda g:g.V().group_count().by(__.both_e().count()))],
16461646
'g_V_both_groupCountXaX_out_capXaX_selectXkeysX_unfold_both_groupCountXaX_capXaX': [(lambda g:g.V().both().group_count('a').out().cap('a').select(Column.keys).unfold().both().group_count('a').cap('a'))],
16471647
'g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX': [(lambda g:g.V().has('person', 'name', 'marko').both('knows').group_count().by(__.values('name').fold()))],
1648+
'g_V_outXcreatedX_groupCount_byXnameX_byXageX': [(lambda g:g.V().out('created').group_count().by('name').by('age'))],
1649+
'g_V_outXcreatedX_groupCountXxX_byXnameX_byXageX': [(lambda g:g.V().out('created').group_count('x').by('name').by('age'))],
16481650
'g_VX1X_out_injectXv2X_name': [(lambda g, vid1=None,v2=None:g.V(vid1).out().inject(v2).values('name'))],
16491651
'g_VX1X_out_name_injectXdanielX_asXaX_mapXlengthX_path': [], # skipping as it contains a lambda
16501652
'g_VX1X_injectXg_VX4XX_out_name': [(lambda g, vid1=None,v2=None:g.V(vid1).inject(v2).out().values('name'))],

0 commit comments

Comments
 (0)