Sfoglia il codice sorgente

Avoid precision loss in DocValueFormat.RAW#parseLong (#49063)

tjwilson90 6 anni fa
parent
commit
262cb958a5

+ 6 - 0
server/src/main/java/org/elasticsearch/search/DocValueFormat.java

@@ -115,6 +115,12 @@ public interface DocValueFormat extends NamedWriteable {
 
         @Override
         public long parseLong(String value, boolean roundUp, LongSupplier now) {
+            try {
+                // Prefer parsing as a long to avoid losing precision
+                return Long.parseLong(value);
+            } catch (NumberFormatException e) {
+                // retry as a double
+            }
             double d = Double.parseDouble(value);
             if (roundUp) {
                 d = Math.ceil(d);

+ 3 - 2
server/src/test/java/org/elasticsearch/search/DocValueFormatTests.java

@@ -168,6 +168,7 @@ public class DocValueFormatTests extends ESTestCase {
     public void testRawParse() {
         assertEquals(-1L, DocValueFormat.RAW.parseLong("-1", randomBoolean(), null));
         assertEquals(1L, DocValueFormat.RAW.parseLong("1", randomBoolean(), null));
+        assertEquals(Long.MAX_VALUE - 2, DocValueFormat.RAW.parseLong(Long.toString(Long.MAX_VALUE - 2), randomBoolean(), null));
         // not checking exception messages as they could depend on the JVM
         expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("", randomBoolean(), null));
         expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("abc", randomBoolean(), null));
@@ -176,8 +177,8 @@ public class DocValueFormatTests extends ESTestCase {
         assertEquals(1d, DocValueFormat.RAW.parseDouble("1", randomBoolean(), null), 0d);
         assertEquals(.5, DocValueFormat.RAW.parseDouble("0.5", randomBoolean(), null), 0d);
         // not checking exception messages as they could depend on the JVM
-        expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("", randomBoolean(), null));
-        expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("abc", randomBoolean(), null));
+        expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseDouble("", randomBoolean(), null));
+        expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseDouble("abc", randomBoolean(), null));
 
         assertEquals(new BytesRef("abc"), DocValueFormat.RAW.parseBytesRef("abc"));
     }