This is an automated email from the ASF dual-hosted git repository.

hxb pushed a commit to branch release-1.15
in repository https://gitbox.apache.org/repos/asf/flink.git


The following commit(s) were added to refs/heads/release-1.15 by this push:
     new 507b93eef2a [FLINK-29477][python] Fix ClassCastException when collect 
primitive array
507b93eef2a is described below

commit 507b93eef2af79ef2ad5752e1271e5c8915bb15f
Author: Juntao Hu <[email protected]>
AuthorDate: Fri Sep 30 13:01:30 2022 +0800

    [FLINK-29477][python] Fix ClassCastException when collect primitive array
    
    This closes #21016.
---
 .../pyflink/datastream/tests/test_data_stream.py   |  9 ++-
 .../flink/api/common/python/PythonBridgeUtils.java | 80 ++++++++++++++++++++--
 2 files changed, 83 insertions(+), 6 deletions(-)

diff --git a/flink-python/pyflink/datastream/tests/test_data_stream.py 
b/flink-python/pyflink/datastream/tests/test_data_stream.py
index 3fd0a9fb372..e3f05936ed1 100644
--- a/flink-python/pyflink/datastream/tests/test_data_stream.py
+++ b/flink-python/pyflink/datastream/tests/test_data_stream.py
@@ -312,11 +312,18 @@ class DataStreamTests(object):
                       decimal.Decimal('2000000000000000000.061111111111111'
                                       '11111111111111'))]
         expected = test_data
-        ds = self.env.from_collection(test_data).map(lambda a: a)
+        ds = self.env.from_collection(test_data)
         with ds.execute_and_collect() as results:
             actual = [result for result in results]
             self.assert_equals_sorted(expected, actual)
 
+        test_data = [[1, 2, 3], [4, 5]]
+        expected = test_data
+        ds = self.env.from_collection(test_data, 
type_info=Types.PRIMITIVE_ARRAY(Types.INT()))
+        with ds.execute_and_collect() as results:
+            actual = [r for r in results]
+            self.assert_equals_sorted(expected, actual)
+
     def test_keyed_map(self):
         from pyflink.util.java_utils import get_j_env_configuration
         from pyflink.common import Configuration
diff --git 
a/flink-python/src/main/java/org/apache/flink/api/common/python/PythonBridgeUtils.java
 
b/flink-python/src/main/java/org/apache/flink/api/common/python/PythonBridgeUtils.java
index 10d9cf30b7e..ebf4f346de3 100644
--- 
a/flink-python/src/main/java/org/apache/flink/api/common/python/PythonBridgeUtils.java
+++ 
b/flink-python/src/main/java/org/apache/flink/api/common/python/PythonBridgeUtils.java
@@ -44,6 +44,7 @@ import org.apache.flink.table.types.logical.RowType;
 import org.apache.flink.table.types.logical.TimeType;
 import org.apache.flink.table.types.logical.TimestampType;
 import org.apache.flink.types.Row;
+import org.apache.flink.util.Preconditions;
 
 import net.razorvine.pickle.Pickler;
 import net.razorvine.pickle.Unpickler;
@@ -270,12 +271,16 @@ public final class PythonBridgeUtils {
                 return fieldBytes;
             } else if (dataType instanceof BasicArrayTypeInfo
                     || dataType instanceof PrimitiveArrayTypeInfo) {
-                Object[] objects = (Object[]) obj;
+                Object[] objects;
+                TypeInformation<?> elementType;
+                if (dataType instanceof BasicArrayTypeInfo) {
+                    objects = (Object[]) obj;
+                    elementType = ((BasicArrayTypeInfo<?, ?>) 
dataType).getComponentInfo();
+                } else {
+                    objects = primitiveArrayConverter(obj, dataType);
+                    elementType = ((PrimitiveArrayTypeInfo<?>) 
dataType).getComponentType();
+                }
                 List<Object> serializedElements = new 
ArrayList<>(objects.length);
-                TypeInformation<?> elementType =
-                        dataType instanceof BasicArrayTypeInfo
-                                ? ((BasicArrayTypeInfo<?, ?>) 
dataType).getComponentInfo()
-                                : ((PrimitiveArrayTypeInfo<?>) 
dataType).getComponentType();
                 for (Object object : objects) {
                     
serializedElements.add(getPickledBytesFromJavaObject(object, elementType));
                 }
@@ -323,6 +328,71 @@ public final class PythonBridgeUtils {
         }
     }
 
+    private static Object[] primitiveArrayConverter(
+            Object array, TypeInformation<?> arrayTypeInfo) {
+        Preconditions.checkArgument(arrayTypeInfo instanceof 
PrimitiveArrayTypeInfo);
+        Preconditions.checkArgument(array.getClass().isArray());
+        Object[] objects;
+        if 
(PrimitiveArrayTypeInfo.BOOLEAN_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo))
 {
+            boolean[] booleans = (boolean[]) array;
+            objects = new Object[booleans.length];
+            for (int i = 0; i < booleans.length; i++) {
+                objects[i] = booleans[i];
+            }
+        } else if 
(PrimitiveArrayTypeInfo.BYTE_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo)) {
+            byte[] bytes = (byte[]) array;
+            objects = new Object[bytes.length];
+            for (int i = 0; i < bytes.length; i++) {
+                objects[i] = bytes[i];
+            }
+        } else if 
(PrimitiveArrayTypeInfo.SHORT_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo)) {
+            short[] shorts = (short[]) array;
+            objects = new Object[shorts.length];
+            for (int i = 0; i < shorts.length; i++) {
+                objects[i] = shorts[i];
+            }
+        } else if 
(PrimitiveArrayTypeInfo.INT_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo)) {
+            int[] ints = (int[]) array;
+            objects = new Object[ints.length];
+            for (int i = 0; i < ints.length; i++) {
+                objects[i] = ints[i];
+            }
+        } else if 
(PrimitiveArrayTypeInfo.LONG_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo)) {
+            long[] longs = (long[]) array;
+            objects = new Object[longs.length];
+            for (int i = 0; i < longs.length; i++) {
+                objects[i] = longs[i];
+            }
+        } else if 
(PrimitiveArrayTypeInfo.FLOAT_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo)) {
+            float[] floats = (float[]) array;
+            objects = new Object[floats.length];
+            for (int i = 0; i < floats.length; i++) {
+                objects[i] = floats[i];
+            }
+        } else if 
(PrimitiveArrayTypeInfo.DOUBLE_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo)) 
{
+            double[] doubles = (double[]) array;
+            objects = new Object[doubles.length];
+            for (int i = 0; i < doubles.length; i++) {
+                objects[i] = doubles[i];
+            }
+        } else if 
(PrimitiveArrayTypeInfo.CHAR_PRIMITIVE_ARRAY_TYPE_INFO.equals(arrayTypeInfo)) {
+            char[] chars = (char[]) array;
+            objects = new Object[chars.length];
+            for (int i = 0; i < chars.length; i++) {
+                objects[i] = chars[i];
+            }
+        } else {
+            throw new UnsupportedOperationException(
+                    String.format(
+                            "Primitive array of %s is not supported in PyFlink 
yet",
+                            ((PrimitiveArrayTypeInfo<?>) arrayTypeInfo)
+                                    .getComponentType()
+                                    .getTypeClass()
+                                    .getSimpleName()));
+        }
+        return objects;
+    }
+
     public static Object getPickledBytesFromRow(Row row, DataType[] dataTypes) 
throws IOException {
         LogicalType[] logicalTypes =
                 Arrays.stream(dataTypes).map(f -> 
f.getLogicalType()).toArray(LogicalType[]::new);

Reply via email to