Yaoxuan Wu created FLINK-41294:
----------------------------------

             Summary: PyFlink batch: pandas UDAF over a RANGE frame with 
CURRENT ROW or n PRECEDING / FOLLOWING reads the ORDER BY key as TIMESTAMP(3) 
and gets wrong frames for INT and DECIMAL keys
                 Key: FLINK-41294
                 URL: https://issues.apache.org/jira/browse/FLINK-41294
             Project: Flink
          Issue Type: Bug
          Components: API / Python
    Affects Versions: 2.3.0, 2.1.1, 2.0.1
            Reporter: Yaoxuan Wu


{code:python}
from pyflink.table import EnvironmentSettings, TableEnvironment, DataTypes as D
from pyflink.table.udf import udaf
t_env = TableEnvironment.create(EnvironmentSettings.in_batch_mode())
t_env.get_config().set('parallelism.default', '1')
t_env.create_temporary_view('t', t_env.from_elements([(-2,), (-1,), (0,), 
(3,)], D.ROW([D.FIELD('o', D.INT())])))
t_env.create_temporary_function('pandas_count',
    udaf(lambda s: len(s), result_type=D.BIGINT(), func_type='pandas'))

w = "OVER (ORDER BY o RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)"
t_env.execute_sql(f"SELECT o, COUNT(o) {w} AS c FROM t").print()         # c = 
1, 2, 3, 4
t_env.execute_sql(f"SELECT o, pandas_count(o) {w} AS c FROM t").print()  # c = 
1, 4, 4, 4
{code}
Same data: {{RANGE BETWEEN 1 PRECEDING AND CURRENT ROW}} gives native 1, 2, 2, 
1 and pandas 1, 4, 4, 4. With a DECIMAL(10, 2) key, {{UNBOUNDED PRECEDING AND 
CURRENT ROW}} is correct but {{1 PRECEDING AND CURRENT ROW}} gives pandas 1, 1, 
1, 1. With a DECIMAL(38, 10) key pandas gives 4, 4, 4, 4 for both frames. 
BIGINT keys are correct.

Cause: 
{{BatchArrowPythonOverWindowAggregateFunctionOperator.invokeCurrentBatch}} 
computes the boundaries of every bounded RANGE window from 
{{curData.getTimestamp(inputTimeFieldIndex, 3).getMillisecond()}} and compares 
the neighbouring rows the same way ({{isInCurrentOverWindow}}). 
{{BatchExecPythonOverAggregate}} passes the index of the ORDER BY field 
({{sortSpec.getFieldIndices()[0]}}) whatever its type, and a {{CURRENT ROW}} 
bound is a bounded bound (boundary 0 from 
{{OverAggregateUtil.getLongBoundary}}), so even {{UNBOUNDED PRECEDING AND 
CURRENT ROW}} takes this path. Reading the key as a compact TIMESTAMP(3) 
({{BinaryRowData.getTimestamp}}: {{segments[0].getLong(getFieldOffset(pos))}}) 
reads its 8-byte fixed-length slot as a long: right for BIGINT; for DECIMAL(p 
<= 18) it is the unscaled value, so the frame offset is applied in units of 
10^-scale (1 PRECEDING becomes 0.01 PRECEDING for DECIMAL(10, 2)); for a 
negative INT only the low 4 bytes are set (-2 reads as 4294967294); for 
DECIMAL(p > 18) the slot holds an offset and length rather than the value. 
Since the boundary scan only moves forward, keys read out of order also give 
wrong frames for later rows.

Reproduces on 2.0.1, 2.2.1, 2.3.0 and master.




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

Reply via email to