This is an automated email from the ASF dual-hosted git repository.
snuyanzin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/master by this push:
new fed133939df [FLINK-40218][core] Store a `JSON` number literal in the
`VARIANT` builder like `PARSE_JSON`
fed133939df is described below
commit fed133939df542016dbbb0e892a11eacbf9b93ae
Author: Ramin Gharib <[email protected]>
AuthorDate: Sat Oct 10 14:38:07 2026 +0200
[FLINK-40218][core] Store a `JSON` number literal in the `VARIANT` builder
like `PARSE_JSON`
---
.../variant/BinaryVariantInternalBuilder.java | 23 ++++++
.../variant/BinaryVariantInternalBuilderTest.java | 81 ++++++++++++++++++++++
2 files changed, 104 insertions(+)
diff --git
a/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
b/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
index 0143f81da41..7e1d952343e 100644
---
a/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
+++
b/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
@@ -345,6 +345,29 @@ public class BinaryVariantInternalBuilder {
}
}
+ /**
+ * Appends a JSON number literal the way {@link #parseJson(String,
boolean)} stores it: as the
+ * smallest integer that holds it, else as a decimal, else as a double. A
caller that holds JSON
+ * in another form, such as a tree built by its own Jackson, uses this so
its numbers match
+ * {@code PARSE_JSON}. The literal is read with the same parser and number
handling as {@code
+ * PARSE_JSON}, so surrounding whitespace is allowed.
+ *
+ * @throws IOException if {@code literal} is not exactly one JSON number,
or is out of the range
+ * of a double. The builder must not be used after that.
+ */
+ void appendJsonNumber(String literal) throws IOException {
+ try (JsonParser parser = JSON_FACTORY.createParser(literal)) {
+ final JsonToken token = parser.nextToken();
+ if (token != JsonToken.VALUE_NUMBER_INT && token !=
JsonToken.VALUE_NUMBER_FLOAT) {
+ throw new JsonParseException(parser, "Expected a JSON number
but got " + token);
+ }
+ buildJson(parser);
+ if (parser.nextToken() != null) {
+ throw new JsonParseException(parser, "Unexpected content after
the JSON number");
+ }
+ }
+ }
+
// The variant spec requires a scale in [0, 38] and a precision of at most
38.
private static BigDecimal toVariantDecimal(BigDecimal d) {
BigDecimal result = d;
diff --git
a/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
b/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
index 5a8e2c07254..2043381dc76 100644
---
a/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
+++
b/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
@@ -310,4 +310,85 @@ class BinaryVariantInternalBuilderTest {
// A negative scale is rescaled to 0.
Arguments.of(5L, -1, DECIMAL4));
}
+
+ @ParameterizedTest
+ @ValueSource(
+ strings = {
+ "0",
+ "-0",
+ "127",
+ "128",
+ "-129",
+ "32768",
+ "2147483648",
+ "9223372036854775807",
+ "-9223372036854775808",
+ // Beyond a long: a decimal while it fits 38 digits, then a
double.
+ "9223372036854775808",
+ "-9223372036854775809",
+ "123456789012345678901234567890123456789",
+ "3.14",
+ "-1.5",
+ "0.10",
+ "0.000000000000000000000000000000000000001",
+ "1e10",
+ "1E10",
+ "1e+10",
+ "1e-10",
+ "-1.5e3",
+ "1e308",
+ // Whitespace around a value is valid JSON.
+ " 1.5\n"
+ })
+ void testAppendJsonNumberMatchesParseJson(final String literal) throws
IOException {
+ final BinaryVariantInternalBuilder builder = new
BinaryVariantInternalBuilder(false);
+ builder.appendJsonNumber(literal);
+
+ assertThat(builder.build())
+ .isEqualTo(BinaryVariantInternalBuilder.parseJson(literal,
false));
+ }
+
+ @ParameterizedTest
+ @ValueSource(
+ strings = {
+ // Locale-specific separators.
+ "1,5",
+ "1.000,5",
+ "1'000",
+ // Accepted by Java's number parsers, but not by JSON.
+ "+5",
+ "0x1p4",
+ "0x1.8p3",
+ "10d",
+ "1.5f",
+ "1" + (char) 0x06F8,
+ "NaN",
+ "Infinity",
+ "-Infinity",
+ // Incomplete or malformed.
+ "",
+ "-",
+ "01",
+ "-01",
+ "1.",
+ ".5",
+ "1e",
+ "1e+",
+ "1.5.5",
+ "--1",
+ // Another JSON value, or more than one.
+ "\"5\"",
+ "true",
+ "null",
+ "[1]",
+ "5 6",
+ // A JSON number outside the range of a double.
+ "1e400",
+ "-1e400"
+ })
+ void testAppendJsonNumberRejectsInvalidLiterals(final String literal) {
+ final BinaryVariantInternalBuilder builder = new
BinaryVariantInternalBuilder(false);
+
+ assertThatThrownBy(() ->
builder.appendJsonNumber(literal)).isInstanceOf(IOException.class);
+ }
}