This is an automated email from the ASF dual-hosted git repository.
xiazcy pushed a commit to branch 3.8-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/3.8-dev by this push:
new 76598e16e5 CTR fix bug in `asNumber()` where for `longValue()` method,
BigDecimal needs to be truncated before calling `longValueExact()` or else it
throws
76598e16e5 is described below
commit 76598e16e5927b4e0bd3485b8bc2db99f6ba0fec
Author: xiazcy <[email protected]>
AuthorDate: Tue Oct 28 17:51:10 2025 -0700
CTR fix bug in `asNumber()` where for `longValue()` method, BigDecimal
needs to be truncated before calling `longValueExact()` or else it throws
---
.../org/apache/tinkerpop/gremlin/util/NumberHelper.java | 8 +++++++-
.../process/traversal/step/map/AsNumberStepTest.java | 9 +++++++++
.../test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 1 +
gremlin-go/driver/cucumber/gremlin.go | 1 +
.../javascript/gremlin-javascript/test/cucumber/gremlin.js | 1 +
gremlin-python/src/main/python/radish/gremlin.py | 1 +
.../tinkerpop/gremlin/test/features/map/AsNumber.feature | 14 ++++++++++++++
7 files changed, 34 insertions(+), 1 deletion(-)
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
index 3fcdc95109..6effd17b72 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.GType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
+import java.math.RoundingMode;
import java.util.function.Function;
import java.util.function.BiFunction;
@@ -793,7 +794,12 @@ public final class NumberHelper {
}
try {
- if (num.getClass().equals(BigDecimal.class)) return ((BigDecimal)
num).longValueExact();
+ if (num.getClass().equals(BigDecimal.class)) {
+ // need to truncate the decimal places or else
longValueExact() will throw
+ BigDecimal truncated = ((BigDecimal) num).setScale(0,
RoundingMode.DOWN);
+ return truncated.longValueExact();
+ }
+
return num.getClass().equals(BigInteger.class) ? ((BigInteger)
num).longValueExact() : num.longValue();
} catch (ArithmeticException ae) {
throw new ArithmeticException(msgOverflow);
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
index 397313151e..7c8984214a 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
@@ -51,6 +51,10 @@ public class AsNumberStepTest extends StepTest {
assertEquals(3.14f, __.__(3.14).asNumber(GType.FLOAT).next());
assertEquals(3.14, __.__(3.14f).asNumber(GType.DOUBLE).next());
assertEquals(3.14, __.__(3.14f).asNumber(GType.DOUBLE).next());
+ assertEquals(3, __.__(new
BigDecimal("3.14")).asNumber(GType.INT).next());
+ assertEquals(3L, __.__(new
BigDecimal("3.14")).asNumber(GType.LONG).next());
+ assertEquals(-3, __.__(new
BigDecimal("-3.14")).asNumber(GType.INT).next());
+ assertEquals(-3L, __.__(new
BigDecimal("-3.14")).asNumber(GType.LONG).next());
assertEquals(1, __.__("1").asNumber(GType.INT).next());
assertEquals(1, __.__("1").asNumber().next());
assertEquals((byte) 1, __.__("1").asNumber(GType.BYTE).next());
@@ -273,6 +277,11 @@ public class AsNumberStepTest extends StepTest {
__.__(new BigDecimal(Long.MAX_VALUE+"1")).asNumber(GType.SHORT).next();
}
+ @Test(expected = ArithmeticException.class)
+ public void shouldThrowOverflowExceptionWhenBigDecimalToLongOverflows() {
+ __.__(new BigDecimal(Long.MAX_VALUE+"1")).asNumber(GType.LONG).next();
+ }
+
@Test(expected = ArithmeticException.class)
public void shouldThrowOverflowExceptionWhenFloatToLongOverflows() {
__.__(new Float(Long.MAX_VALUE+"1")).asNumber(GType.LONG).next();
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 72a6e338a1..174c7c385b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -969,6 +969,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_injectXnullX_asNumberXGType_INTX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(null).AsNumber(GType.Int)}},
{"g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().As("a").Out("knows").As("b").Math("a +
b").By("age").AsNumber(GType.Int)}},
{"g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSideEffect("x", 100).V().Values<object>("age").Math("_ +
x").AsNumber(GType.Long)}},
+ {"g_V_valuesXageX_asString_asNumberXGType_DOUBLEX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Values<object>("age").AsString().AsNumber(GType.Double)}},
{"g_injectX1_2X_asString", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(1,
2).AsString()}},
{"g_injectX1_2X_asStringXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(1, 2).AsString<object>(Scope.Local)}},
{"g_injectXlist_1_2X_asStringXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { 1, 2
}).AsString<object>(Scope.Local)}},
diff --git a/gremlin-go/driver/cucumber/gremlin.go
b/gremlin-go/driver/cucumber/gremlin.go
index cb5dd3a53e..2db3eaa111 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -939,6 +939,7 @@ var translationMap = map[string][]func(g
*gremlingo.GraphTraversalSource, p map[
"g_injectXnullX_asNumberXGType_INTX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.Inject(nil).AsNumber(gremlingo.GType.Int)}},
"g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V().As("a").Out("knows").As("b").Math("a +
b").By("age").AsNumber(gremlingo.GType.Int)}},
"g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.WithSideEffect("x",
100).V().Values("age").Math("_ + x").AsNumber(gremlingo.GType.Long)}},
+ "g_V_valuesXageX_asString_asNumberXGType_DOUBLEX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().Values("age").AsString().AsNumber(gremlingo.GType.Double)}},
"g_injectX1_2X_asString": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1,
2).AsString()}},
"g_injectX1_2X_asStringXlocalX": {func(g *gremlingo.GraphTraversalSource,
p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1,
2).AsString(gremlingo.Scope.Local)}},
"g_injectXlist_1_2X_asStringXlocalX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject([]interface{}{1,
2}).AsString(gremlingo.Scope.Local)}},
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 90cb2c61bc..7412f18ec4 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
@@ -970,6 +970,7 @@ const gremlins = {
g_injectXnullX_asNumberXGType_INTX: [function({g}) { return
g.inject(null).asNumber(GType.int) }],
g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX:
[function({g}) { return g.V().as("a").out("knows").as("b").math("a +
b").by("age").asNumber(GType.int) }],
g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX:
[function({g}) { return g.withSideEffect("x", 100).V().values("age").math("_ +
x").asNumber(GType.long) }],
+ g_V_valuesXageX_asString_asNumberXGType_DOUBLEX: [function({g}) { return
g.V().values("age").asString().asNumber(GType.double) }],
g_injectX1_2X_asString: [function({g}) { return g.inject(1, 2).asString()
}],
g_injectX1_2X_asStringXlocalX: [function({g}) { return g.inject(1,
2).asString(Scope.local) }],
g_injectXlist_1_2X_asStringXlocalX: [function({g}) { return g.inject([1,
2]).asString(Scope.local) }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py
b/gremlin-python/src/main/python/radish/gremlin.py
index aeeee9e77d..9e9c26988d 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -942,6 +942,7 @@ world.gremlins = {
'g_injectXnullX_asNumberXGType_INTX': [(lambda
g:g.inject(None).as_number(GType.INT))],
'g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX':
[(lambda g:g.V().as_('a').out('knows').as_('b').math('a +
b').by('age').as_number(GType.INT))],
'g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX':
[(lambda g:g.with_side_effect('x', 100).V().values('age').math('_ +
x').as_number(GType.LONG))],
+ 'g_V_valuesXageX_asString_asNumberXGType_DOUBLEX': [(lambda
g:g.V().values('age').as_string().as_number(GType.DOUBLE))],
'g_injectX1_2X_asString': [(lambda g:g.inject(1, 2).as_string())],
'g_injectX1_2X_asStringXlocalX': [(lambda g:g.inject(1,
2).as_string(Scope.local))],
'g_injectXlist_1_2X_asStringXlocalX': [(lambda g:g.inject([1,
2]).as_string(Scope.local))],
diff --git
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
index 50acb6b3ad..831c0b8c4b 100644
---
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
+++
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
@@ -311,3 +311,17 @@ Feature: Step - asNumber()
| d[127].l |
| d[132].l |
| d[135].l |
+
+ Scenario: g_V_valuesXageX_asString_asNumberXGType_DOUBLEX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().values("age").asString().asNumber(GType.DOUBLE)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29.0].d |
+ | d[27.0].d |
+ | d[32.0].d |
+ | d[35.0].d |