Richard Chen created SPARK-59992:
------------------------------------

             Summary: element_at and array index are wrongly non-nullable under 
ANSI mode when the index is nullable
                 Key: SPARK-59992
                 URL: https://issues.apache.org/jira/browse/SPARK-59992
             Project: Spark
          Issue Type: Bug
          Components: SQL
    Affects Versions: 4.2.0
            Reporter: Richard Chen


With ANSI mode enabled, ElementAt and GetArrayItem report nullable = false for 
a non-foldable index whenever the array is non-nullable and its elements are 
non-nullable (e.g. array('a', 'b')). The nullability of the index is ignored, 
even though both expressions are null-intolerant and return NULL for a NULL 
index.

The optimizer trusts this flag. NullPropagation truncates a Coalesce after its 
first non-nullable child, so a fallback such as coalesce(element_at(arr, idx), 
'z') is removed and the query returns NULL instead of 'z'. The result column is 
also declared non-nullable while carrying nulls, so collecting it through an 
encoder fails with EXPRESSION_DECODING_FAILED, and writing it to a NOT NULL 
column fails.

Repro, with spark.sql.ansi.enabled=true:
{code:sql}
SELECT coalesce(element_at(array('a', 'b'), CAST(nullif(id, 0) AS INT)), 'z') 
AS v1,
       coalesce(array('a', 'b')[CAST(nullif(id, 0) AS INT) - 1], 'z') AS v2
FROM range(2);
{code}
Expected rows: (z, z) and (a, a). Actual: the optimized plan contains no 
coalesce (e.g. "if ((id = 0)) null else element_at([a,b], cast(id as int), 
None, true)"), the first row is (NULL, NULL), and the schema declares both 
columns non-nullable.

The cause is GetArrayItemUtil.computeNullabilityFromArray, shared by both 
expressions:
{code:scala}
} else {
  if (failOnError) arrayElementNullable || child.nullable else true
}
{code}
The fix is to also include ordinal.nullable in the ANSI branch; a non-nullable 
index keeps the existing non-nullable result.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

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

Reply via email to