Sangkyoon Nam created FLINK-41496:
-------------------------------------

             Summary: Python Table API thread mode overwrites ROW values inside 
ARRAY and MAP
                 Key: FLINK-41496
                 URL: https://issues.apache.org/jira/browse/FLINK-41496
             Project: Flink
          Issue Type: Bug
          Components: API / Python
            Reporter: Sangkyoon Nam


In Python thread mode, the Table API converters can overwrite ROW values inside 
an ARRAY or MAP with a later row's values, both for UDF arguments and for UDF 
results. No exception is raised, and process mode returns the expected values. 
I reproduced it on master at {{cac69274d4e}} and haven't tested released 
versions.

Reproducer:
{code:python}
import sys

from pyflink.common import Row
from pyflink.table import DataTypes, EnvironmentSettings, TableEnvironment
from pyflink.table.udf import udf

table_env = TableEnvironment.create(EnvironmentSettings.in_batch_mode())
config = table_env.get_config()
config.set("python.execution-mode", "thread")
config.set("python.executable", sys.executable)
config.set("python.client.executable", sys.executable)

child = DataTypes.ROW([DataTypes.FIELD("x", DataTypes.BIGINT())])
table = table_env.sql_query(
    "SELECT ARRAY[CAST(ROW(1) AS ROW<x BIGINT>), CAST(ROW(2) AS ROW<x BIGINT>)] 
AS a")

identity = udf(lambda v: v, result_type=DataTypes.ARRAY(child))
constant = udf(lambda v: [Row(10), Row(20)], result_type=DataTypes.ARRAY(child))

with table.select(identity(table.a), constant(table.a)).execute().collect() as 
rows:
    print([tuple(row) for row in rows])
{code}
Expected output (also what process mode prints):
{noformat}
[([<Row(1)>, <Row(2)>], [<Row(10)>, <Row(20)>])]
{noformat}
Thread mode:
{noformat}
[([<Row(2)>, <Row(2)>], [<Row(20)>, <Row(20)>])]
{noformat}
{{MAP<STRING, ROW<...>>}} values are affected too, and an 
{{ARRAY<ARRAY<ROW<...>>>}} of {{[[Row(1), Row(2)], [Row(3)]]}} comes back as 
{{[[Row(3), Row(3)], [Row(3)]]}}.

Cause: {{RowDataConverter}} in 
{{org.apache.flink.table.runtime.typeutils.PythonTypeUtils}} returns the same 
{{Row}} / {{Object[]}} on every call (reuse added in FLINK-28549, 1.16.0). That 
is safe for a top-level row, but {{ArrayDataConverter}} and 
{{MapDataConverter}} store each converted element, so later elements overwrite 
earlier ones.

FLINK-41228 fixed the same issue in the DataStream converters by disabling 
reuse below arrays, lists and maps. I have a patch applying the same approach 
to the Table API converters, with tests in {{PythonTypeUtilsTest}} and 
{{test_udf.py}}. It's based on my FLINK-41426 null-handling fix. Could you 
assign this to me?



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to