Skip to content

Commit ddfb1b6

Browse files
committed
Merge branch '3.8-dev'
2 parents baf9477 + a112cae commit ddfb1b6

15 files changed

Lines changed: 135 additions & 45 deletions

File tree

CHANGELOG.asciidoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,12 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
302302
* Fixed bug in `SubgraphStrategy` where specifying `edges` and `vertices` filters that had `map`-type steps could generate an error.
303303
* Fixed bug in `ReservedKeysVerificationStrategy` where `AddPropertyStep` was not triggering proper validations.
304304
* Fixed bug in `mergeE` where `onCreate` validation of invalid static argument overrides did not trigger until traversal runtime.
305+
* Expand grammar argument types for `coin` and `pagerank` steps to `numericArgument` from `floatArgument`.
305306
* Added `closeSessionPostGraphOp` to the Gremlin Server settings to indicate that the `Session` should be closed on either a successful commit or rollback.
307+
* Added `SessionedChildClient` that borrows connections from a different `Client` for use with `Sessions`.
308+
* Added `reuseConnectionsForSessions` to Java GLV settings to decide whether to use `SessionedChildClient` for remote transactions.
309+
* Added support for Node 22 and 24 alongside Node 20.
310+
* Fixed `cap()` step throwing an error when used mid-traversal in OLAP.
306311
307312
[[release-3-7-5]]
308313
=== TinkerPop 3.7.5 (Release Date: November 12, 2025)

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,6 @@ public Object visitIntegerArgument(final GremlinParser.IntegerArgumentContext ct
130130
}
131131
}
132132

133-
@Override
134-
public Object visitFloatArgument(final GremlinParser.FloatArgumentContext ctx) {
135-
if (ctx.floatLiteral() != null) {
136-
return antlr.genericVisitor.parseFloating(ctx.floatLiteral());
137-
} else {
138-
return visitVariable(ctx.variable());
139-
}
140-
}
141-
142133
@Override
143134
public Object visitStringArgument(final GremlinParser.StringArgumentContext ctx) {
144135
if (ctx.stringLiteral() != null) {

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,10 +1442,6 @@ protected void notImplemented(final ParseTree ctx) {
14421442
/**
14431443
* {@inheritDoc}
14441444
*/
1445-
@Override public T visitFloatArgument(final GremlinParser.FloatArgumentContext ctx) { notImplemented(ctx); return null; }
1446-
/**
1447-
* {@inheritDoc}
1448-
*/
14491445
@Override public T visitStringArgument(final GremlinParser.StringArgumentContext ctx) { notImplemented(ctx); return null; }
14501446
/**
14511447
* {@inheritDoc}

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ public Number parseIntegral(final GremlinParser.IntegerLiteralContext integerLit
6666
/**
6767
* Parse floating literal context and return a floating type number.
6868
*/
69-
public Number parseFloating(final GremlinParser.FloatLiteralContext floatLiteral) {
70-
return (Number) visitFloatLiteral(floatLiteral);
69+
public Number parseNumeric(final GremlinParser.NumericLiteralContext numericLiteral) {
70+
return (Number) visitNumericLiteral(numericLiteral);
7171
}
7272

7373
/**

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ public GraphTraversal visitTraversalMethod_combine_Object(final GremlinParser.Tr
479479
*/
480480
@Override
481481
public GraphTraversal visitTraversalMethod_coin(final GremlinParser.TraversalMethod_coinContext ctx) {
482-
return graphTraversal.coin(((Number) antlr.genericVisitor.visitFloatLiteral(ctx.floatLiteral())).doubleValue());
482+
return graphTraversal.coin(((Number) antlr.genericVisitor.visitNumericLiteral(ctx.numericLiteral())).doubleValue());
483483
}
484484

485485
/**
@@ -1309,7 +1309,7 @@ public GraphTraversal visitTraversalMethod_pageRank_Empty(final GremlinParser.Tr
13091309
*/
13101310
@Override
13111311
public GraphTraversal visitTraversalMethod_pageRank_double(final GremlinParser.TraversalMethod_pageRank_doubleContext ctx) {
1312-
return graphTraversal.pageRank(((Number) antlr.genericVisitor.visitFloatLiteral(ctx.floatLiteral())).doubleValue());
1312+
return graphTraversal.pageRank(((Number) antlr.genericVisitor.visitNumericLiteral(ctx.numericLiteral())).doubleValue());
13131313
}
13141314

13151315
/**

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/MemoryTraversalSideEffects.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,12 @@ public TraversalSideEffects getSideEffects() {
5757
@Override
5858
public void set(final String key, final Object value) {
5959
this.sideEffects.set(key, value);
60-
if (null != this.memory)
60+
61+
// looks like calls to this method are only permitted during setup/terminate (i.e. masterState)
62+
// during worker execution (e.g. cap() firing lazily via a downstream local step), skip the
63+
// memory write to avoid IllegalArgumentException from the distributed memory implementation.
64+
// see TINKERPOP-3210 for an example of how this fails.
65+
if (null != this.memory && this.phase.masterState())
6166
this.memory.set(key, value);
6267
}
6368

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,13 @@ public boolean terminate(final Memory memory) {
329329
MasterExecutor.processMemory(this.traversalMatrix, memory, toProcessTraversers, completedBarriers);
330330
// process all results from barriers locally and when elements are touched, put them in remoteActiveTraversers
331331
MasterExecutor.processTraversers(this.traversal, this.traversalMatrix, toProcessTraversers, remoteActiveTraversers, haltedTraversers, this.haltedTraverserStrategy);
332-
// tell parallel barriers that might not have been active in the last round that they are no longer active
333-
memory.set(COMPLETED_BARRIERS, completedBarriers);
332+
// tell parallel barriers that might not have been active in the last round that they are no longer active.
333+
// accumulate all previously-completed barriers: worker clones start with done=false and need done() called
334+
// for every barrier ever completed (not just the most recent ones) to prevent stale lazy re-evaluation.
335+
// see TINKERPOP-3210 for the lazy cap() re-firing that motivated this change.
336+
final Set<String> allCompletedBarriers = new HashSet<>(memory.get(COMPLETED_BARRIERS));
337+
allCompletedBarriers.addAll(completedBarriers);
338+
memory.set(COMPLETED_BARRIERS, allCompletedBarriers);
334339
if (!remoteActiveTraversers.isEmpty() ||
335340
completedBarriers.stream().map(this.traversalMatrix::getStepById).filter(step -> step instanceof LocalBarrier).findAny().isPresent()) {
336341
// send active traversers back to workers

gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,14 @@ public static Iterable<Object[]> generateTestParameters() {
9393
{Long.class, "x", 0L, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", (short) 0)))},
9494
{Long.class, "x", 0L, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0)))},
9595
{Long.class, "x", 0L, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0L)))},
96-
{Float.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
97-
{Float.class, "0.0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
98-
{Float.class, "0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
99-
{Float.class, "0F", 0.0F, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0F)))},
100-
{Float.class, "x", GValue.of("x", 0.0), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0)))},
101-
{Float.class, "x", GValue.of("x", 0.0F), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0F)))},
102-
{Float.class, "x", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0)))},
103-
{Float.class, "x", 0.0F, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0F)))},
96+
{Object.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
97+
{Object.class, "0.0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
98+
{Object.class, "0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
99+
{Object.class, "0F", 0.0F, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0F)))},
100+
{Object.class, "x", GValue.of("x", 0.0), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0)))},
101+
{Object.class, "x", GValue.of("x", 0.0F), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0F)))},
102+
{Object.class, "x", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0)))},
103+
{Object.class, "x", 0.0F, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0F)))},
104104
{String.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
105105
{String.class, "'test'", "test", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
106106
{String.class, "x", GValue.of("x", "test"), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "test")))},
@@ -142,11 +142,6 @@ public void shouldParse() {
142142
final GremlinParser.IntegerArgumentContext ctx = parser.integerArgument();
143143
return antlrToLanguage.argumentVisitor.parseLong(ctx);
144144
});
145-
} else if (clazz.equals(Float.class)) {
146-
assertParsing(() -> {
147-
final GremlinParser.FloatArgumentContext ctx = parser.floatArgument();
148-
return antlrToLanguage.argumentVisitor.visitFloatArgument(ctx);
149-
});
150145
} else if (clazz.equals(String.class)) {
151146
assertParsing(() -> {
152147
final GremlinParser.StringArgumentContext ctx = parser.stringArgument();

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
355355
{"g_injectX7X_anyXeqX7XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(7).Any(P.Eq(7))}},
356356
{"g_injectXnull_nullX_anyXeqXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(new List<object> { null, null }).Any(P.Eq(null))}},
357357
{"g_injectX3_threeX_anyXeqX3XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(new List<object> { 3, "three" }).Any(P.Eq(3))}},
358-
{"g_V_coinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Coin(1.0)}},
358+
{"g_V_coinX1_0X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Coin(1.0)}},
359+
{"g_V_coinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Coin(1)}},
359360
{"g_V_coinX0X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Coin(0.0)}},
360361
{"g_withStrategiesXSeedStrategyX_V_order_byXnameX_coinX50X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Order().By("name").Coin(0.5)}},
361362
{"g_VX1X_outXcreatedX_inXcreatedX_cyclicPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("created").In("created").CyclicPath()}},
@@ -2006,6 +2007,9 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
20062007
{"g_V_localXaggregateXaXX_unionXout_inX_localXaggregateXaXX_capXaX_unfold_dedup_valuesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.Aggregate("a")).Union<object>(__.Out(), __.In()).Local<object>(__.Aggregate("a")).Cap<object>("a").Unfold<object>().Dedup().Values<object>("name")}},
20072008
{"g_V_hasXname_joshX_localXaggregateXaXX_outE_hasXweight_ltX1_0XX_inV_localXaggregateXaXX_outE_inV_localXaggregateXaXX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("name", "josh").Local<object>(__.Aggregate("a")).OutE().Has("weight", P.Lt(1.0)).InV().Local<object>(__.Aggregate("a")).OutE().InV().Local<object>(__.Aggregate("a")).Cap<object>("a")}},
20082009
{"g_V_hasLabelXpersonX_localXaggregateXaXX_outE_order_byXweightX_limitX1X_inV_localXaggregateXaXX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Local<object>(__.Aggregate("a")).OutE().Order().By("weight").Limit<object>(1).InV().Local<object>(__.Aggregate("a")).Cap<object>("a")}},
2010+
{"g_V_repeatXaggregateXaXX_timesX2X_capXaX_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat(__.Aggregate("a")).Times(2).Cap<object>("a").Unfold<object>()}},
2011+
{"g_V_aggregateXaX_capXaX_unfold_both", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").Cap<object>("a").Unfold<object>().Both()}},
2012+
{"g_V_aggregateXaX_capXaX_unfold_barrier_both", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").Cap<object>("a").Unfold<object>().Barrier().Both()}},
20092013
{"g_V_fail", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fail()}},
20102014
{"g_V_failXmsgX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fail("msg")}},
20112015
{"g_V_unionXout_failX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Union<object>(__.Out(), __.Fail())}},

gremlin-go/driver/cucumber/gremlin.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
325325
"g_injectX7X_anyXeqX7XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(7).Any(gremlingo.P.Eq(7))}},
326326
"g_injectXnull_nullX_anyXeqXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{nil, nil}).Any(gremlingo.P.Eq(nil))}},
327327
"g_injectX3_threeX_anyXeqX3XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{3, "three"}).Any(gremlingo.P.Eq(3))}},
328-
"g_V_coinX1X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Coin(1.0)}},
328+
"g_V_coinX1_0X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Coin(1.0)}},
329+
"g_V_coinX1X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Coin(1)}},
329330
"g_V_coinX0X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Coin(0.0)}},
330331
"g_withStrategiesXSeedStrategyX_V_order_byXnameX_coinX50X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.SeedStrategy(gremlingo.SeedStrategyConfig{Seed: 999999})).V().Order().By("name").Coin(0.5)}},
331332
"g_VX1X_outXcreatedX_inXcreatedX_cyclicPath": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out("created").In("created").CyclicPath()}},
@@ -1976,6 +1977,9 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
19761977
"g_V_localXaggregateXaXX_unionXout_inX_localXaggregateXaXX_capXaX_unfold_dedup_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Local(gremlingo.T__.Aggregate("a")).Union(gremlingo.T__.Out(), gremlingo.T__.In()).Local(gremlingo.T__.Aggregate("a")).Cap("a").Unfold().Dedup().Values("name")}},
19771978
"g_V_hasXname_joshX_localXaggregateXaXX_outE_hasXweight_ltX1_0XX_inV_localXaggregateXaXX_outE_inV_localXaggregateXaXX_capXaX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", "josh").Local(gremlingo.T__.Aggregate("a")).OutE().Has("weight", gremlingo.P.Lt(1.0)).InV().Local(gremlingo.T__.Aggregate("a")).OutE().InV().Local(gremlingo.T__.Aggregate("a")).Cap("a")}},
19781979
"g_V_hasLabelXpersonX_localXaggregateXaXX_outE_order_byXweightX_limitX1X_inV_localXaggregateXaXX_capXaX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Local(gremlingo.T__.Aggregate("a")).OutE().Order().By("weight").Limit(1).InV().Local(gremlingo.T__.Aggregate("a")).Cap("a")}},
1980+
"g_V_repeatXaggregateXaXX_timesX2X_capXaX_unfold": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Repeat(gremlingo.T__.Aggregate("a")).Times(2).Cap("a").Unfold()}},
1981+
"g_V_aggregateXaX_capXaX_unfold_both": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Aggregate("a").Cap("a").Unfold().Both()}},
1982+
"g_V_aggregateXaX_capXaX_unfold_barrier_both": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Aggregate("a").Cap("a").Unfold().Barrier().Both()}},
19791983
"g_V_fail": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Fail()}},
19801984
"g_V_failXmsgX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Fail("msg")}},
19811985
"g_V_unionXout_failX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Union(gremlingo.T__.Out(), gremlingo.T__.Fail())}},

0 commit comments

Comments
 (0)