Skip to content

Conversation

@hemanthsavasere
Copy link
Contributor

@hemanthsavasere hemanthsavasere commented Oct 28, 2025

Purpose

Linked issue: close #1844

Perform automatic type widening between numeric types when converting POJOs to internal rows. Change from strict and exact type validation to widening conversion from lower to higher data types in POJO field's Java type and the schema's Fluss type.

Implementation Sample Scenarios :
POJO with int field + Schema with BIGINT → SUCCEEDS ✅
POJO with short field + Schema with BIGINT → SUCCEEDS ✅
POJO with int field + Schema with FLOAT → SUCCEEDS ✅
POJO with Long field + Schema with SMALLINT → FAILS (narrowing not supported) ❌

Widening Primitive Conversions :
byte (TINYINT) → short, int, long, float, double
short (SMALLINT) → int, long, float, double
int (INTEGER) → long, float, double
long (BIGINT) → float, double
float (FLOAT) → double

fluss-client

  1. Expanded SUPPORTED_TYPES map in ConverterCommons.java to include all widening-compatible source types for each numeric target type
  2. Added casting logic in PojoToRowConverter.java with dedicated conversion methods for each numeric type (convertToTinyInt, convertToSmallInt, convertToInteger, convertToBigInt, convertToFloat, convertToDouble)

fluss-flink-common

  1. Updated SUPPORTED_TYPES map in PojoToRowConverter.java to include widening-compatible types (both primitives and boxed)
  2. Implemented casting logic in createConverterForField() method with corresponding conversion helper methods

Tests

Added comprehensive tests in PojoToRowConverterTest.java for all widening combinations in fluss-client
Added comprehensive tests in PojoToRowConverterTest.java covering all widening scenarios in fluss-flink-common

Documentation

Updated Java Client documentation (website/docs/apis/java-client.md) with POJO converter usage examples and numeric type widening explanation
Updated Flink DataStream documentation (website/docs/engine-flink/datastream.mdx) with POJO converter notes and widening support details

@hemanthsavasere
Copy link
Contributor Author

@polyzos Can you please review the pull request. Thanks

- `short``int`, `long`, `float`, `double`
- `int``long`, `float`, `double`
- `long``float`, `double`
- `float``double`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NaN
same for double
also would be great to have test for such corner cases

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not clear what about BigInteger/BigDecimal?

Short.class,
Byte.class)); // all numerics can widen to double

// Non-numeric types remain unchanged
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you elaborate why

map.put(DataTypeRoot.DECIMAL, setOf(BigDecimal.class));

is considered as non-numeric?

Comment on lines +353 to +367
if (v instanceof Float) {
return ((Float) v).doubleValue(); // float -> double widening
}
if (v instanceof Long) {
return ((Long) v).doubleValue(); // long -> double widening
}
if (v instanceof Integer) {
return ((Integer) v).doubleValue(); // int -> double widening
}
if (v instanceof Short) {
return ((Short) v).doubleValue(); // short -> double widening
}
if (v instanceof Byte) {
return ((Byte) v).doubleValue(); // byte -> double widening
}
Copy link
Contributor

@snuyanzin snuyanzin Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder this can be replaced with something like

if (v instanceof Number) {
  return ((Number) v).doubleValue();
}

similar for other places

// ----------------------- Numeric Type Widening Tests -----------------------

@Test
public void testByteToSmallIntWidening() {
Copy link
Contributor

@snuyanzin snuyanzin Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void testByteToSmallIntWidening() {
void testByteToSmallIntWidening() {

nit: here and in other places no need for public in junit5

Comment on lines +189 to +217
@Test
public void testIntToBigIntWidening() {
RowType table = RowType.builder().field("orderId", DataTypes.BIGINT()).build();
RowType projection = table;

PojoToRowConverter<IntFieldPojo> converter =
PojoToRowConverter.of(IntFieldPojo.class, table, projection);

IntFieldPojo pojo = new IntFieldPojo();
pojo.orderId = 123456;
GenericRow row = converter.toRow(pojo);

assertThat(row.getLong(0)).isEqualTo(123456L);
}

@Test
public void testShortToBigIntWidening() {
RowType table = RowType.builder().field("quantity", DataTypes.BIGINT()).build();
RowType projection = table;

PojoToRowConverter<ShortFieldPojo> converter =
PojoToRowConverter.of(ShortFieldPojo.class, table, projection);

ShortFieldPojo pojo = new ShortFieldPojo();
pojo.quantity = (short) 999;
GenericRow row = converter.toRow(pojo);

assertThat(row.getLong(0)).isEqualTo(999L);
}
Copy link
Contributor

@snuyanzin snuyanzin Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these and other tests in this class are pretty similar
can we parameterize them?

@polyzos
Copy link
Contributor

polyzos commented Oct 29, 2025

@hemanthsavasere can you remove the documentation? This functionality is meant for internal use.
The goal is to update the existing Java client to use this functionality under the hood so it's transparent to the users.
So we don't need to document it, as it won't be exposed to users directly

@polyzos
Copy link
Contributor

polyzos commented Oct 29, 2025

@snuyanzin thank you for reviewing this and your thoughtful feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relax conditions for converters

3 participants