This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new a7f06795 feat(java): store OptionalInt, OptionalLong, OptionalDouble
same as nullable values (#2338)
a7f06795 is described below
commit a7f06795423906db6dbd371098da1746f4cf1c3d
Author: Steven Schlansker <[email protected]>
AuthorDate: Wed Jun 18 20:21:45 2025 -0700
feat(java): store OptionalInt, OptionalLong, OptionalDouble same as
nullable values (#2338)
## What does this PR do?
currently, optional wrappers are stored as a bean with two fields -
present and value, taking 32 bytes
with this change, stored as nullable primitive, taking 8 bytes plus 1
bit for null
this is a breaking change to the row format, but since support is
relatively recent, hopefully that is ok?
---
.../fory/builder/BaseObjectCodecBuilder.java | 1 +
.../java/org/apache/fory/builder/CodecBuilder.java | 15 +++--
.../java/org/apache/fory/codegen/Expression.java | 15 +++--
.../main/java/org/apache/fory/type/TypeUtils.java | 9 +++
.../apache/fory/codegen/ExpressionVisitorTest.java | 1 +
.../format/encoder/BaseBinaryEncoderBuilder.java | 66 +++++++++++++++++++---
.../fory/format/encoder/RowEncoderBuilder.java | 31 ++++++++--
.../apache/fory/format/row/binary/BinaryUtils.java | 24 ++++++--
.../org/apache/fory/format/type/TypeInference.java | 9 ++-
9 files changed, 141 insertions(+), 30 deletions(-)
diff --git
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
index 8834ab3f..2f8efe1e 100644
---
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
+++
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
@@ -1041,6 +1041,7 @@ public abstract class BaseObjectCodecBuilder extends
CodecBuilder {
} else {
return new ForEach(
collection,
+ false,
(i, elem) ->
writeContainerElement(
exprHolder.get("buffer"),
diff --git
a/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java
b/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java
index 800490c3..cf37d8ff 100644
--- a/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java
@@ -127,6 +127,10 @@ public abstract class CodecBuilder {
return ctx.sourcePublicAccessible(cls);
}
+ protected boolean fieldNullable(Descriptor descriptor) {
+ return false;
+ }
+
protected Expression tryInlineCast(Expression expression, TypeRef<?>
targetType) {
return tryCastIfPublic(expression, targetType, true);
}
@@ -162,9 +166,6 @@ public abstract class CodecBuilder {
return expression;
}
- // left null check in sub class encode method to reduce data dependence.
- private final boolean fieldNullable = false;
-
protected Reference getRecordCtrHandle() {
String fieldName = "_record_ctr_";
Reference fieldRef = fieldMap.get(fieldName);
@@ -192,8 +193,9 @@ public abstract class CodecBuilder {
TypeRef<?> fieldType = descriptor.getTypeRef();
Class<?> rawType = descriptor.getRawType();
String fieldName = descriptor.getName();
+ boolean fieldNullable = fieldNullable(descriptor);
if (isInterface) {
- return new Invoke(inputBeanExpr, descriptor.getName(), fieldName,
fieldType);
+ return new Invoke(inputBeanExpr, descriptor.getName(), fieldName,
fieldType, fieldNullable);
}
if (isRecord) {
return getRecordFieldValue(inputBeanExpr, descriptor);
@@ -243,6 +245,7 @@ public abstract class CodecBuilder {
fieldType = OBJECT_TYPE;
}
String fieldName = descriptor.getName();
+ boolean fieldNullable = fieldNullable(descriptor);
if (Modifier.isPublic(beanClass.getModifiers())) {
Preconditions.checkNotNull(descriptor.getReadMethod());
return new Invoke(
@@ -280,7 +283,8 @@ public abstract class CodecBuilder {
Expression inputObject, Class<?> cls, Descriptor descriptor) {
Reference fieldRef = getReflectField(cls, descriptor.getField());
// boolean fieldNullable = !descriptor.getTypeToken().isPrimitive();
- Invoke getObj = new Invoke(fieldRef, "get", OBJECT_TYPE, fieldNullable,
inputObject);
+ Invoke getObj =
+ new Invoke(fieldRef, "get", OBJECT_TYPE, fieldNullable(descriptor),
inputObject);
return new Cast(getObj, descriptor.getTypeRef(), descriptor.getName());
}
@@ -289,6 +293,7 @@ public abstract class CodecBuilder {
Expression inputObject, Class<?> cls, Descriptor descriptor) {
String fieldName = descriptor.getName();
Expression fieldOffsetExpr = getFieldOffset(cls, descriptor);
+ boolean fieldNullable = fieldNullable(descriptor);
if (descriptor.getTypeRef().isPrimitive()) {
// ex: Platform.UNSAFE.getFloat(obj, fieldOffset)
Preconditions.checkArgument(!fieldNullable);
diff --git
a/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java
b/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java
index 3cd4a771..95592426 100644
--- a/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java
+++ b/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java
@@ -891,7 +891,8 @@ public interface Expression {
String value =
StringUtils.format(
"((${withCast})${target})", "withCast", withCast, "target",
targetExprCode.value());
- return new ExprCode(codeBuilder.toString(), FalseLiteral,
Code.variable(rawType, value));
+ return new ExprCode(
+ codeBuilder.toString(), targetExprCode.isNull(),
Code.variable(rawType, value));
} else {
String castedValue = ctx.newName(castedValueNamePrefix);
if (StringUtils.isNotBlank(targetExprCode.code())) {
@@ -2243,17 +2244,21 @@ public interface Expression {
@ClosureVisitable final SerializableBiFunction<Expression, Expression,
Expression> action;
private final TypeRef<?> elementType;
+ private final boolean elementNullable;
/**
* inputObject.type() must be multi-dimension array or Collection, not
allowed to be primitive
* array
*/
public ForEach(
- Expression inputObject, SerializableBiFunction<Expression, Expression,
Expression> action) {
+ Expression inputObject,
+ boolean elementNullable,
+ SerializableBiFunction<Expression, Expression, Expression> action) {
super(inputObject);
this.inputObject = inputObject;
+ this.elementNullable = elementNullable;
this.action = action;
- TypeRef elementType;
+ TypeRef<?> elementType;
if (inputObject.type().isArray()) {
elementType = inputObject.type().getComponentType();
} else {
@@ -2265,11 +2270,13 @@ public interface Expression {
public ForEach(
Expression inputObject,
TypeRef<?> beanType,
+ boolean elementNullable,
SerializableBiFunction<Expression, Expression, Expression> action) {
super(inputObject);
this.inputObject = inputObject;
this.action = action;
this.elementType = beanType;
+ this.elementNullable = elementNullable;
}
@Override
@@ -2287,7 +2294,7 @@ public interface Expression {
String i = ctx.newName("i");
String elemValue = ctx.newName("elemValue");
Expression elementExpr =
- action.apply(new Reference(i), new Reference(elemValue, elementType,
false));
+ action.apply(new Reference(i), new Reference(elemValue, elementType,
elementNullable));
ExprCode elementExprCode = elementExpr.genCode(ctx);
if (inputObject.type().isArray()) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
index 6bc0b4b0..a4af2479 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
@@ -44,6 +44,9 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.fory.collection.IdentityMap;
@@ -104,6 +107,9 @@ public class TypeUtils {
public static final TypeRef<?> MAP_ENTRY_TYPE = TypeRef.of(Map.Entry.class);
public static final TypeRef<?> HASHMAP_TYPE = TypeRef.of(HashMap.class);
public static final TypeRef<?> OPTIONAL_TYPE = TypeRef.of(Optional.class);
+ public static final TypeRef<?> OPTIONAL_INT_TYPE =
TypeRef.of(OptionalInt.class);
+ public static final TypeRef<?> OPTIONAL_LONG_TYPE =
TypeRef.of(OptionalLong.class);
+ public static final TypeRef<?> OPTIONAL_DOUBLE_TYPE =
TypeRef.of(OptionalDouble.class);
public static final TypeRef<?> OBJECT_TYPE = TypeRef.of(Object.class);
public static Type ITERATOR_RETURN_TYPE;
@@ -159,6 +165,9 @@ public class TypeUtils {
SUPPORTED_TYPES.add(TIMESTAMP_TYPE);
SUPPORTED_TYPES.add(INSTANT_TYPE);
SUPPORTED_TYPES.add(OPTIONAL_TYPE);
+ SUPPORTED_TYPES.add(OPTIONAL_INT_TYPE);
+ SUPPORTED_TYPES.add(OPTIONAL_LONG_TYPE);
+ SUPPORTED_TYPES.add(OPTIONAL_DOUBLE_TYPE);
}
static {
diff --git
a/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
b/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
index cbbc43e3..0ab92115 100644
---
a/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
+++
b/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
@@ -52,6 +52,7 @@ public class ExpressionVisitorTest {
Expression.ForEach forLoop =
new Expression.ForEach(
list,
+ false,
(i, expr) -> ((Expression.ListExpression)
(holder.get("e2"))).add(holder.get("e1")));
List<Expression> expressions = new ArrayList<>();
new ExpressionVisitor()
diff --git
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
index 7ff21902..640520ac 100644
---
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
+++
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
@@ -30,6 +30,9 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
import java.util.Set;
import org.apache.arrow.vector.types.pojo.Field;
import org.apache.arrow.vector.types.pojo.Schema;
@@ -164,15 +167,21 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
serializeFor(
ordinal, newInputObject, writer, rewrittenType, arrowField,
visitedCustomTypes);
return new If(
- ExpressionUtils.eqNull(inputObject),
+ new Expression.IsNull(inputObject),
new Invoke(writer, "setNullAt", ordinal),
doSerialize);
} else if (rawType == Optional.class) {
TypeRef<?> elemType = TypeUtils.getTypeArguments(typeRef).get(0);
Invoke orNull =
- new Invoke(inputObject, "orElse", TypeUtils.OBJECT_TYPE, new
Expression.Null(elemType));
+ new Invoke(
+ inputObject,
+ "orElse",
+ "",
+ TypeUtils.OBJECT_TYPE,
+ true,
+ new Expression.Null(elemType));
Expression unwrapped =
- new If(ExpressionUtils.eqNull(inputObject), new
Expression.Null(elemType), orNull);
+ new If(new Expression.IsNull(inputObject), new
Expression.Null(elemType), orNull);
return serializeFor(
ordinal,
new Expression.Cast(unwrapped, elemType),
@@ -192,6 +201,13 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
} else if (rawType == java.math.BigInteger.class) {
Invoke value = new Invoke(inputObject, "toByteArray",
TypeRef.of(byte[].class));
return setValueOrNull(writer, ordinal, inputObject, value);
+ } else if (rawType == OptionalInt.class) {
+ return serializeForOptional(ordinal, inputObject, writer, "getAsInt",
TypeUtils.INT_TYPE);
+ } else if (rawType == OptionalLong.class) {
+ return serializeForOptional(ordinal, inputObject, writer, "getAsLong",
TypeUtils.LONG_TYPE);
+ } else if (rawType == OptionalDouble.class) {
+ return serializeForOptional(
+ ordinal, inputObject, writer, "getAsDouble", TypeUtils.DOUBLE_TYPE);
} else if (rawType == java.time.LocalDate.class) {
StaticInvoke value =
new StaticInvoke(
@@ -306,6 +322,7 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
ForEach forEach =
new ForEach(
inputObject,
+ !rawType.getComponentType().isPrimitive(),
(i, value) ->
serializeFor(
i,
@@ -323,6 +340,7 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
ForEach forEach =
new ForEach(
listFromIterable,
+ !TypeUtils.getElementType(typeRef).isPrimitive(),
(i, value) ->
serializeFor(
i,
@@ -338,6 +356,7 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
ForEach forEach =
new ForEach(
inputObject,
+ !TypeUtils.getElementType(typeRef).isPrimitive(),
(i, value) ->
serializeFor(
i,
@@ -426,7 +445,7 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
expressions.add(setOffsetAndSize);
return new If(
- ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), expressions);
+ new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), expressions);
}
/**
@@ -486,7 +505,7 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
setOffsetAndSize);
return new If(
- ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), expression);
+ new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), expression);
}
/**
@@ -515,14 +534,34 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
increaseWriterIndexToAligned,
setOffsetAndSize);
return new If(
- ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), expression);
+ new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), expression);
+ }
+
+ protected Expression serializeForOptional(
+ Expression ordinal,
+ Expression inputObject,
+ Expression writer,
+ String getMethod,
+ TypeRef<?> wrapType) {
+ Class<?> primType = TypeUtils.unwrap(wrapType.getRawType());
+ If value =
+ new If(
+ new Expression.LogicalAnd(
+ true,
+ new Expression.Not(new Expression.IsNull(inputObject)),
+ Invoke.inlineInvoke(inputObject, "isPresent",
TypeUtils.PRIMITIVE_BOOLEAN_TYPE)),
+ new Invoke(inputObject, getMethod, TypeRef.of(primType)),
+ new Expression.Null(wrapType),
+ true,
+ wrapType);
+ return setValueOrNull(writer, ordinal, value, value);
}
protected Expression setValueOrNull(
Expression writer, Expression ordinal, Expression inputObject,
Expression value) {
Expression action = new Invoke(writer, "write", ordinal, value);
return new If(
- ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), action);
+ new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt",
ordinal), action);
}
/**
@@ -558,6 +597,10 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
return value;
} else if (rawType == java.math.BigInteger.class) {
return new NewInstance(TypeUtils.BIG_INTEGER_TYPE, value);
+ } else if (rawType == OptionalInt.class
+ || rawType == OptionalLong.class
+ || rawType == OptionalDouble.class) {
+ return deserializeForOptional(value, TypeRef.of(rawType));
} else if (rawType == java.time.LocalDate.class) {
return new StaticInvoke(
DateTimeUtils.class, "daysToLocalDate", TypeUtils.LOCAL_DATE_TYPE,
false, value);
@@ -654,6 +697,15 @@ public abstract class BaseBinaryEncoderBuilder extends
CodecBuilder {
}
}
+ protected Expression deserializeForOptional(Expression value, TypeRef<?>
type) {
+ return new Expression.If(
+ new Expression.IsNull(value),
+ new Expression.StaticInvoke(type.getRawType(), "empty", type),
+ new Expression.StaticInvoke(type.getRawType(), "of", type, value),
+ false,
+ type);
+ }
+
/**
* Create a java collection. Create a {@link ArrayList} if
<code>typeToken</code> is super class
* of {@link ArrayList}; Create a {@link HashSet} if <code>typeToken</code>
is super class of
diff --git
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
index 459d5c75..f8c16a38 100644
---
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
+++
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
@@ -27,6 +27,9 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
import java.util.SortedMap;
import org.apache.arrow.vector.types.pojo.Field;
import org.apache.arrow.vector.types.pojo.Schema;
@@ -115,6 +118,11 @@ public class RowEncoderBuilder extends
BaseBinaryEncoderBuilder {
return "RowCodec";
}
+ @Override
+ protected boolean fieldNullable(Descriptor descriptor) {
+ return descriptor.isNullable();
+ }
+
@Override
public String genCode() {
ctx.setPackage(CodeGenerator.getPackage(beanClass));
@@ -237,7 +245,13 @@ public class RowEncoderBuilder extends
BaseBinaryEncoderBuilder {
values[i] = value;
expressions.add(value);
Expression.Invoke isNullAt =
- new Expression.Invoke(row, "isNullAt",
TypeUtils.PRIMITIVE_BOOLEAN_TYPE, ordinal);
+ new Expression.Invoke(
+ row,
+ "isNullAt",
+ "f" + i + "_" + d.getName() + "IsNull",
+ TypeUtils.PRIMITIVE_BOOLEAN_TYPE,
+ false,
+ ordinal);
Expression decode =
new Expression.If(
ExpressionUtils.not(isNullAt),
@@ -271,9 +285,11 @@ public class RowEncoderBuilder extends
BaseBinaryEncoderBuilder {
private static Expression nullValue(TypeRef<?> fieldType) {
Class<?> rawType = fieldType.getRawType();
- if (rawType == Optional.class) {
- return new Expression.StaticInvoke(
- Optional.class, "empty", "", TypeUtils.OPTIONAL_TYPE, false, true);
+ if (rawType == Optional.class
+ || rawType == OptionalInt.class
+ || rawType == OptionalLong.class
+ || rawType == OptionalDouble.class) {
+ return new Expression.StaticInvoke(rawType, "empty", "", fieldType,
false, true);
}
return new Expression.Reference(TypeUtils.defaultValue(rawType),
fieldType);
}
@@ -359,7 +375,12 @@ public class RowEncoderBuilder extends
BaseBinaryEncoderBuilder {
Expression isNotNullAt =
new Expression.Not(
new Expression.Invoke(
- row, "isNullAt", TypeUtils.PRIMITIVE_BOOLEAN_TYPE,
ordinal));
+ row,
+ "isNullAt",
+ fieldName + "IsNull",
+ TypeUtils.PRIMITIVE_BOOLEAN_TYPE,
+ false,
+ ordinal));
assigner = new Expression.If(isNotNullAt, loadIfFieldIsNull);
} else {
assigner = loadIfFieldIsNull;
diff --git
a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
index 345f5f03..29cd2e16 100644
---
a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
+++
b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
@@ -35,13 +35,19 @@ public class BinaryUtils {
return "getBoolean";
} else if (TypeUtils.PRIMITIVE_SHORT_TYPE.equals(type) ||
TypeUtils.SHORT_TYPE.equals(type)) {
return "getInt16";
- } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type) ||
TypeUtils.INT_TYPE.equals(type)) {
+ } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type)
+ || TypeUtils.INT_TYPE.equals(type)
+ || TypeUtils.OPTIONAL_INT_TYPE.equals(type)) {
return "getInt32";
- } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type) ||
TypeUtils.LONG_TYPE.equals(type)) {
+ } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type)
+ || TypeUtils.LONG_TYPE.equals(type)
+ || TypeUtils.OPTIONAL_LONG_TYPE.equals(type)) {
return "getInt64";
} else if (TypeUtils.PRIMITIVE_FLOAT_TYPE.equals(type) ||
TypeUtils.FLOAT_TYPE.equals(type)) {
return "getFloat32";
- } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type) ||
TypeUtils.DOUBLE_TYPE.equals(type)) {
+ } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type)
+ || TypeUtils.DOUBLE_TYPE.equals(type)
+ || TypeUtils.OPTIONAL_DOUBLE_TYPE.equals(type)) {
return "getFloat64";
} else if (TypeUtils.BIG_DECIMAL_TYPE.equals(type)) {
return "getDecimal";
@@ -81,13 +87,19 @@ public class BinaryUtils {
return TypeUtils.PRIMITIVE_BOOLEAN_TYPE;
} else if (TypeUtils.PRIMITIVE_SHORT_TYPE.equals(type) ||
TypeUtils.SHORT_TYPE.equals(type)) {
return TypeUtils.PRIMITIVE_SHORT_TYPE;
- } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type) ||
TypeUtils.INT_TYPE.equals(type)) {
+ } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type)
+ || TypeUtils.INT_TYPE.equals(type)
+ || TypeUtils.OPTIONAL_INT_TYPE.equals(type)) {
return TypeUtils.PRIMITIVE_INT_TYPE;
- } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type) ||
TypeUtils.LONG_TYPE.equals(type)) {
+ } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type)
+ || TypeUtils.LONG_TYPE.equals(type)
+ || TypeUtils.OPTIONAL_LONG_TYPE.equals(type)) {
return TypeUtils.PRIMITIVE_LONG_TYPE;
} else if (TypeUtils.PRIMITIVE_FLOAT_TYPE.equals(type) ||
TypeUtils.FLOAT_TYPE.equals(type)) {
return TypeUtils.PRIMITIVE_FLOAT_TYPE;
- } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type) ||
TypeUtils.DOUBLE_TYPE.equals(type)) {
+ } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type)
+ || TypeUtils.DOUBLE_TYPE.equals(type)
+ || TypeUtils.OPTIONAL_DOUBLE_TYPE.equals(type)) {
return TypeUtils.PRIMITIVE_DOUBLE_TYPE;
} else if (TypeUtils.BIG_DECIMAL_TYPE.equals(type)) {
return TypeUtils.BIG_DECIMAL_TYPE;
diff --git
a/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java
b/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java
index e7a67ce4..7c529423 100644
---
a/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java
+++
b/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java
@@ -28,6 +28,9 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
import org.apache.arrow.vector.complex.MapVector;
import org.apache.arrow.vector.types.DateUnit;
import org.apache.arrow.vector.types.FloatingPointPrecision;
@@ -185,14 +188,14 @@ public class TypeInference {
return field(name, FieldType.nullable((new ArrowType.Int(8, true))));
} else if (rawType == Short.class) {
return field(name, FieldType.nullable((new ArrowType.Int(16, true))));
- } else if (rawType == Integer.class) {
+ } else if (rawType == Integer.class || rawType == OptionalInt.class) {
return field(name, FieldType.nullable((new ArrowType.Int(32, true))));
- } else if (rawType == Long.class) {
+ } else if (rawType == Long.class || rawType == OptionalLong.class) {
return field(name, FieldType.nullable((new ArrowType.Int(64, true))));
} else if (rawType == Float.class) {
return field(
name, FieldType.nullable(new
ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE)));
- } else if (rawType == Double.class) {
+ } else if (rawType == Double.class || rawType == OptionalDouble.class) {
return field(
name, FieldType.nullable(new
ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)));
} else if (rawType == java.math.BigDecimal.class) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]