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 |

Reply via email to