This is an automated email from the ASF dual-hosted git repository. AHeise pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/flink.git
commit 3193e71ae5dd5e0128ff8ffde3a6329e98af4d8d Author: Ramin Gharib <[email protected]> AuthorDate: Mon Sep 28 11:26:36 2026 +0200 [FLINK-40825][table] Keep a stored NaN or infinity when casting VARIANT to FLOAT or DOUBLE Casting a VARIANT to FLOAT or DOUBLE rejected every non-finite result as an overflow, so a VARIANT holding NaN or infinity, for example one read by the Avro converter, could not be read back. The FLOAT cast now rejects only a finite value that does not fit, such as 1e40, and keeps a stored NaN or infinity. The DOUBLE cast needs no check, since every numeric kind fits a double. --- .../planner/functions/casting/CastRulesTest.java | 11 +++++++++++ .../table/runtime/functions/VariantCastUtils.java | 19 ++++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/casting/CastRulesTest.java b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/casting/CastRulesTest.java index c560e8d1f82..cfe2b641bfd 100644 --- a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/casting/CastRulesTest.java +++ b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/casting/CastRulesTest.java @@ -1998,11 +1998,22 @@ class CastRulesTest { VARIANT(), VARIANT_BUILDER.of(new BigDecimal("123.456")), 123.456f) // a magnitude a FLOAT cannot represent is still rejected .fail(VARIANT(), VARIANT_BUILDER.of(1e40d), TableRuntimeException.class) + // a stored NaN or infinity is not an overflow and is kept + .fromCase(VARIANT(), VARIANT_BUILDER.of(Double.NaN), Float.NaN) + .fromCase( + VARIANT(), + VARIANT_BUILDER.of(Double.POSITIVE_INFINITY), + Float.POSITIVE_INFINITY) .fail(VARIANT(), VARIANT_BUILDER.of("x"), TableRuntimeException.class), CastTestSpecBuilder.testCastTo(DOUBLE()) .fromCase(VARIANT(), VARIANT_BUILDER.of(1.5d), 1.5d) .fromCase(VARIANT(), VARIANT_BUILDER.of(1.5f), 1.5d) .fromCase(VARIANT(), VARIANT_BUILDER.of(3), 3.0d) + .fromCase(VARIANT(), VARIANT_BUILDER.of(Double.NaN), Double.NaN) + .fromCase( + VARIANT(), + VARIANT_BUILDER.of(Float.NEGATIVE_INFINITY), + Double.NEGATIVE_INFINITY) .fromCase( VARIANT(), VARIANT_BUILDER.of(new BigDecimal("123.456")), 123.456d) .fail(VARIANT(), VARIANT_BUILDER.of("x"), TableRuntimeException.class), diff --git a/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/VariantCastUtils.java b/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/VariantCastUtils.java index 9a7ef8b4915..9f2deeb71d4 100644 --- a/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/VariantCastUtils.java +++ b/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/VariantCastUtils.java @@ -177,23 +177,24 @@ public final class VariantCastUtils { /** * Reads any numeric variant as a {@code float}. Dropping decimal digits is expected of an - * approximate type, but a magnitude outside the {@code FLOAT} range is rejected. + * approximate type, but a finite magnitude outside the {@code FLOAT} range is rejected. A + * stored {@code NaN} or infinity is kept as is. */ public static float toFloat(Variant variant) { - final float value = numeric(variant, "FLOAT").floatValue(); - if (!Float.isFinite(value)) { + final Number number = numeric(variant, "FLOAT"); + final float value = number.floatValue(); + if (!Float.isFinite(value) && Double.isFinite(number.doubleValue())) { throw overflow(variant.get(), "FLOAT"); } return value; } - /** Reads any numeric variant as a {@code double}. See {@link #toFloat(Variant)}. */ + /** + * Reads any numeric variant as a {@code double}. Every numeric kind fits the {@code DOUBLE} + * range, so only decimal digits can be dropped, and a stored {@code NaN} or infinity is kept. + */ public static double toDouble(Variant variant) { - final double value = numeric(variant, "DOUBLE").doubleValue(); - if (!Double.isFinite(value)) { - throw overflow(variant.get(), "DOUBLE"); - } - return value; + return numeric(variant, "DOUBLE").doubleValue(); } /**
