Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,39 @@ final class ConverterCommons {
private static Map<DataTypeRoot, Set<Class<?>>> createSupportedTypes() {
Map<DataTypeRoot, Set<Class<?>>> map = new HashMap<>();
map.put(DataTypeRoot.BOOLEAN, setOf(Boolean.class));

// Numeric types with widening support
map.put(DataTypeRoot.TINYINT, setOf(Byte.class));
map.put(DataTypeRoot.SMALLINT, setOf(Short.class));
map.put(DataTypeRoot.INTEGER, setOf(Integer.class));
map.put(DataTypeRoot.BIGINT, setOf(Long.class));
map.put(DataTypeRoot.FLOAT, setOf(Float.class));
map.put(DataTypeRoot.DOUBLE, setOf(Double.class));
map.put(DataTypeRoot.SMALLINT, setOf(Short.class, Byte.class)); // byte can widen to short
map.put(
DataTypeRoot.INTEGER,
setOf(Integer.class, Short.class, Byte.class)); // byte, short can widen to int
map.put(
DataTypeRoot.BIGINT,
setOf(
Long.class,
Integer.class,
Short.class,
Byte.class)); // smaller ints can widen to long
map.put(
DataTypeRoot.FLOAT,
setOf(
Float.class,
Long.class,
Integer.class,
Short.class,
Byte.class)); // all ints can widen to float
map.put(
DataTypeRoot.DOUBLE,
setOf(
Double.class,
Float.class,
Long.class,
Integer.class,
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?

map.put(DataTypeRoot.CHAR, setOf(String.class, Character.class));
map.put(DataTypeRoot.STRING, setOf(String.class, Character.class));
map.put(DataTypeRoot.BINARY, setOf(byte[].class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,23 @@ private PojoType.Property requireProperty(String fieldName) {
private static FieldToRow createFieldConverter(PojoType.Property prop, DataType fieldType) {
switch (fieldType.getTypeRoot()) {
case BOOLEAN:
case BINARY:
case BYTES:
return prop::read; // No casting needed

case TINYINT:
return (obj) -> convertToTinyInt(prop, prop.read(obj));
case SMALLINT:
return (obj) -> convertToSmallInt(prop, prop.read(obj));
case INTEGER:
return (obj) -> convertToInteger(prop, prop.read(obj));
case BIGINT:
return (obj) -> convertToBigInt(prop, prop.read(obj));
case FLOAT:
return (obj) -> convertToFloat(prop, prop.read(obj));
case DOUBLE:
case BINARY:
case BYTES:
return prop::read;
return (obj) -> convertToDouble(prop, prop.read(obj));

case CHAR:
case STRING:
return (obj) -> convertTextValue(fieldType, prop, prop.read(obj));
Expand Down Expand Up @@ -234,6 +242,135 @@ private static FieldToRow createFieldConverter(PojoType.Property prop, DataType
prop.name));
}

/** Converts a numeric POJO property to TINYINT (Byte). */
private static @Nullable Byte convertToTinyInt(PojoType.Property prop, @Nullable Object v) {
if (v == null) {
return null;
}
if (v instanceof Byte) {
return (Byte) v;
}
throw new IllegalArgumentException(
String.format(
"Field %s cannot be converted to TINYINT. Type: %s",
prop.name, v.getClass().getName()));
}

/** Converts a numeric POJO property to SMALLINT (Short) with widening support. */
private static @Nullable Short convertToSmallInt(PojoType.Property prop, @Nullable Object v) {
if (v == null) {
return null;
}
if (v instanceof Short) {
return (Short) v;
}
if (v instanceof Byte) {
return ((Byte) v).shortValue(); // byte -> short widening
}
throw new IllegalArgumentException(
String.format(
"Field %s cannot be converted to SMALLINT. Type: %s",
prop.name, v.getClass().getName()));
}

/** Converts a numeric POJO property to INTEGER (Integer) with widening support. */
private static @Nullable Integer convertToInteger(PojoType.Property prop, @Nullable Object v) {
if (v == null) {
return null;
}
if (v instanceof Integer) {
return (Integer) v;
}
if (v instanceof Short) {
return ((Short) v).intValue(); // short -> int widening
}
if (v instanceof Byte) {
return ((Byte) v).intValue(); // byte -> int widening
}
throw new IllegalArgumentException(
String.format(
"Field %s cannot be converted to INTEGER. Type: %s",
prop.name, v.getClass().getName()));
}

/** Converts a numeric POJO property to BIGINT (Long) with widening support. */
private static @Nullable Long convertToBigInt(PojoType.Property prop, @Nullable Object v) {
if (v == null) {
return null;
}
if (v instanceof Long) {
return (Long) v;
}
if (v instanceof Integer) {
return ((Integer) v).longValue(); // int -> long widening
}
if (v instanceof Short) {
return ((Short) v).longValue(); // short -> long widening
}
if (v instanceof Byte) {
return ((Byte) v).longValue(); // byte -> long widening
}
throw new IllegalArgumentException(
String.format(
"Field %s cannot be converted to BIGINT. Type: %s",
prop.name, v.getClass().getName()));
}

/** Converts a numeric POJO property to FLOAT (Float) with widening support. */
private static @Nullable Float convertToFloat(PojoType.Property prop, @Nullable Object v) {
if (v == null) {
return null;
}
if (v instanceof Float) {
return (Float) v;
}
if (v instanceof Long) {
return ((Long) v).floatValue(); // long -> float widening
}
if (v instanceof Integer) {
return ((Integer) v).floatValue(); // int -> float widening
}
if (v instanceof Short) {
return ((Short) v).floatValue(); // short -> float widening
}
if (v instanceof Byte) {
return ((Byte) v).floatValue(); // byte -> float widening
}
throw new IllegalArgumentException(
String.format(
"Field %s cannot be converted to FLOAT. Type: %s",
prop.name, v.getClass().getName()));
}

/** Converts a numeric POJO property to DOUBLE (Double) with widening support. */
private static @Nullable Double convertToDouble(PojoType.Property prop, @Nullable Object v) {
if (v == null) {
return null;
}
if (v instanceof Double) {
return (Double) v;
}
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
}
Comment on lines +353 to +367
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

throw new IllegalArgumentException(
String.format(
"Field %s cannot be converted to DOUBLE. Type: %s",
prop.name, v.getClass().getName()));
}

private interface FieldToRow {
Object readAndConvert(Object pojo) throws Exception;
}
Expand Down
Loading