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

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

> SimplifyExtractValueOps folds an out-of-bounds array index to NULL under 
> ANSI, suppressing INVALID_ARRAY_INDEX and corrupting the result's nullability
> ------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: SPARK-58431
>                 URL: https://issues.apache.org/jira/browse/SPARK-58431
>             Project: Spark
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions: 4.0.0
>            Reporter: Josh Rosen
>            Priority: Major
>              Labels: correctness, pull-request-available
>
> This is a report of a correctness bug reachable under default configuration 
> on Spark 4.x (ANSI mode is now enabled by default). A query that must raise 
> {{INVALID_ARRAY_INDEX}} instead returns a fabricated value of {{{}0{}}}, 
> silently.
>  
> {{SimplifyExtractValueOps}} rewrites {{array(...)[i]}} when the index is a 
> literal ({{{}ComplexTypes.scala{}}}):
>  
> {code:java}
> case ga @ GetArrayItem(CreateArray(elems, _), IntegerLiteral(idx), _) =>
>   if (idx >= 0 && idx < elems.size) {
>     elems(idx)
>   } else {
>     // out of bounds, mimic the runtime behavior and return null
>     Literal(null, ga.dataType)
>   } {code}
> The comment states the intent: mimic the runtime behavior. That was accurate 
> when the rule was written (SPARK-18601, 2.2.0), but SPARK-33386 (3.1.1) 
> changed the runtime behavior: under ANSI, an out-of-bounds array access 
> _raises_ rather than returning null. The rule was never updated, and it does 
> not consult {{GetArrayItem.failOnError}} (which defaults to 
> {{{}SQLConf.get.ansiEnabled{}}}).
>  
> This causes two problems:
>  * The error is suppressed.
>  * Under ANSI {{GetArrayItem}} declares itself *non-nullable* (it throws 
> instead of returning null), so substituting a null literal places a NULL in a 
> slot the schema marks non-nullable. Depending on the downstream consumer, 
> this can return either NULL (incorrect under ANSI) or as the type's zero 
> value (also incorrect).
>  
> *Repro* (default configuration on 4.x; add {{SET 
> spark.sql.ansi.enabled=true}} on older versions):
>  
> {code:java}
> SET spark.sql.ansi.enabled=true;
> CREATE TABLE arr_src(c INT) USING parquet;
> INSERT INTO arr_src VALUES (1);
> SELECT array(c, 2, 3)[5] AS v FROM arr_src;
> -- prints: NULL       (expected under ANSI: INVALID_ARRAY_INDEX error)
> SELECT count(*) FROM arr_src WHERE array(c, 2, 3)[5] IS NULL;
> -- prints: 0          (the value that just printed NULL matches no IS NULL 
> filter)
> SELECT array(c, 2, 3)[5] IS NULL AS n FROM arr_src;
> -- prints: false
> SELECT sum(array(c,2,3)[5]) AS s, count(array(c,2,3)[5]) AS n FROM arr_src;
> -- prints: NULL, 1    (count treats it as one NON-null value; sum of it is 
> null) {code}
> No consistent value can produce those four outputs together. {*}Which symptom 
> the corrupted slot surfaces as is read-path-dependent{*}: the spark-sql CLI's 
> row rendering honors the physical null bit and prints {{{}NULL{}}}, while 
> {{Dataset.collect()}} (Scala/Java/Python APIs) trusts the declared 
> {{{}nullable = false{}}}, elides the null check, and materializes a 
> fabricated {{0.}}
>  
> Affected versions: the fold dates from 2.2.0, but it only became incorrect 
> when SPARK-33386 (3.1.1) made ANSI out-of-bounds access raise. So 3.1.1+ with 
> ANSI enabled, and {*}4.x by default{*}.



--
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