[ 
https://issues.apache.org/jira/browse/SPARK-60875?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated SPARK-60875:
-----------------------------------
    Labels: pull-request-available  (was: )

> Recursive CTE reads NULLs written into nested types of the anchor back as 0
> ---------------------------------------------------------------------------
>
>                 Key: SPARK-60875
>                 URL: https://issues.apache.org/jira/browse/SPARK-60875
>             Project: Spark
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions: 4.4.0
>            Reporter: Stevo Mitric
>            Priority: Major
>              Labels: pull-request-available
>
> The self-reference of a recursive CTE (UnionLoopRef) is typed with the 
> anchor's output types; only top-level nullability is widened (SPARK-52430). 
> If the anchor builds an array, map or struct from non-null values, e.g. 
> array(c) or map('k', c), the element, value or field type stays non-nullable. 
> When the recursive step writes a NULL there, the next iteration reads it back 
> through generated code that skips the null check, so the NULL silently 
> becomes 0:
> {code:sql}
> CREATE OR REPLACE TEMPORARY VIEW parts AS SELECT id AS part_id, id AS cost 
> FROM range(200);
> WITH RECURSIVE bom(lvl, part_id, costs) AS (
>   SELECT 0, part_id, array(cost) FROM parts
>   UNION ALL
>   SELECT lvl + 1, part_id, IF(lvl = 0, array(CAST(NULL AS BIGINT)), 
> array(costs[0] + 1))
>   FROM bom WHERE lvl < 2
> )
> SELECT lvl, count(*), count_if(costs[0] IS NULL), sum(costs[0]) FROM bom 
> GROUP BY lvl ORDER BY lvl;
> -- actual:   0 200 0 19900 / 1 200 200 NULL / 2 200 0 200
> -- expected: 0 200 0 19900 / 1 200 200 NULL / 2 200 200 NULL
> {code}
> The same happens for map values (info['k'] returns 0 instead of NULL) and for 
> arrays inside structs. A NULL struct element inside an array throws a 
> NullPointerException instead. A column that only copies another column (b = 
> a) is also affected once a's NULLs reach it.
> This happens with the default configuration. Steps larger than 
> spark.sql.cteRecursionAnchorRowsLimitToConvertToLocalRelation (100 rows) are 
> always affected. Smaller steps are converted to a LocalRelation and are 
> affected when the recursive step also reads a non-local relation (e.g. a join 
> with a table), because the step then runs through generated code.
> Related, same cause: when another column of the recursion needs a cast, a 
> recursive step that writes a NULL into such a nested type fails analysis 
> instead:
> {code:sql}
> WITH RECURSIVE t(n, m, arr) AS (
>   SELECT 1, CAST(1 AS BIGINT), ARRAY(1)
>   UNION ALL
>   SELECT n + 1, n + 1, ARRAY(CAST(NULL AS INT)) FROM t WHERE n < 3
> )
> SELECT * FROM t;
> -- [CANNOT_MERGE_INCOMPATIBLE_DATA_TYPE] Failed to merge incompatible data 
> types "ARRAY<INT>" and "ARRAY<INT>"
> {code}



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

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

Reply via email to