yusufyildiz34 commented on code in PR #18508:
URL: https://github.com/apache/iceberg/pull/18508#discussion_r4327153187


##########
flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/RowDataWrapper.java:
##########
@@ -84,79 +92,119 @@ public <T> void set(int pos, T value) {
         "Could not set a field in the RowDataWrapper because rowData is 
read-only");
   }
 
-  private interface PositionalGetter<T> {
-    T get(RowData data, int pos);
+  private RowDataWrapper copyFor(RowData data) {
+    return new RowDataWrapper(types, getters).wrap(data);
+  }
+
+  private static RowData.FieldGetter buildGetter(
+      LogicalType logicalType, Type type, int pos, boolean 
reuseStructWrappers) {
+    RowData.FieldGetter fieldGetter = 
FlinkRowData.createFieldGetter(logicalType, pos);
+    if (reuseStructWrappers && logicalType instanceof RowType rowType) {
+      // A struct field is read one row at a time, so its wrapper can be 
reused.
+      RowDataWrapper structWrapper = new RowDataWrapper(rowType, 
type.asStructType());
+      return row -> structWrapper.wrap((RowData) 
fieldGetter.getFieldOrNull(row));
+    }
+
+    // get() returns null fields before calling a getter, so values are never 
null here.
+    Function<Object, Object> converter = buildConverter(logicalType, type);
+    return row -> converter.apply(fieldGetter.getFieldOrNull(row));
+  }
+
+  private static Function<Object, Object> buildConverter(LogicalType 
logicalType, Type type) {
+    return switch (logicalType.getTypeRoot()) {
+      case TINYINT -> value -> ((Byte) value).intValue();
+      case SMALLINT -> value -> ((Short) value).intValue();
+      case CHAR, VARCHAR -> Object::toString;
+      case BINARY, VARBINARY ->
+          Type.TypeID.UUID == type.typeId()
+              ? value -> UUIDUtil.convert((byte[]) value)
+              : value -> ByteBuffer.wrap((byte[]) value);
+      case DECIMAL -> value -> ((DecimalData) value).toBigDecimal();
+      case TIME_WITHOUT_TIME_ZONE ->
+          // Flink's time is milliseconds (int), Iceberg's time is 
microseconds (long)
+          value -> ((Integer) value).longValue() * 1_000;
+      case TIMESTAMP_WITHOUT_TIME_ZONE ->
+          type.typeId() == Type.TypeID.TIMESTAMP_NANO
+              ? value -> DateTimeUtil.nanosFromTimestamp(((TimestampData) 
value).toLocalDateTime())
+              : value ->
+                  DateTimeUtil.microsFromTimestamp(((TimestampData) 
value).toLocalDateTime());
+      case TIMESTAMP_WITH_LOCAL_TIME_ZONE ->
+          type.typeId() == Type.TypeID.TIMESTAMP_NANO
+              ? value -> {
+                TimestampData timestampData = (TimestampData) value;
+                return timestampData.getMillisecond() * 1_000_000L
+                    + timestampData.getNanoOfMillisecond();
+              }
+              : value -> {
+                TimestampData timestampData = (TimestampData) value;
+                return timestampData.getMillisecond() * 1000L
+                    + timestampData.getNanoOfMillisecond() / 1000;
+              };
+      case ROW -> {
+        // Values read together, like list elements, need their own wrappers. 
The template
+        // doesn't reuse struct wrappers, so its getters can be shared by the 
copies.
+        RowDataWrapper template =
+            new RowDataWrapper(
+                (RowType) logicalType, type.asStructType(), false /* new 
wrapper per value */);
+        yield value -> template.copyFor((RowData) value);
+      }
+      case ARRAY -> {
+        LogicalType elementType = ((ArrayType) logicalType).getElementType();
+        ArrayData.ElementGetter elementGetter = 
FlinkRowData.createElementGetter(elementType);
+        Function<Object, Object> elementConverter =
+            buildConverter(elementType, type.asListType().elementType());
+        yield value -> toList((ArrayData) value, elementGetter, 
elementConverter);
+      }
+      case MAP -> {
+        MapType mapType = (MapType) logicalType;
+        Types.MapType icebergMapType = type.asMapType();
+        ArrayData.ElementGetter keyGetter = 
FlinkRowData.createElementGetter(mapType.getKeyType());
+        ArrayData.ElementGetter valueGetter =
+            FlinkRowData.createElementGetter(mapType.getValueType());
+        Function<Object, Object> keyConverter =
+            buildConverter(mapType.getKeyType(), icebergMapType.keyType());
+        Function<Object, Object> valueConverter =
+            buildConverter(mapType.getValueType(), icebergMapType.valueType());
+        yield value -> toMap((MapData) value, keyGetter, keyConverter, 
valueGetter, valueConverter);
+      }
+      default -> Function.identity();

Review Comment:
   Done in fe531933f, thanks!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to