Ramin Gharib created FLINK-40794:
------------------------------------

             Summary: CAST in Table API ignores input nullability when the 
target type is NOT NULL
                 Key: FLINK-40794
                 URL: https://issues.apache.org/jira/browse/FLINK-40794
             Project: Flink
          Issue Type: Bug
          Components: Table SQL / Planner
            Reporter: Ramin Gharib
            Assignee: Ramin Gharib


In the Table API, a CAST to a target written with .notNull() is planned as NOT 
NULL even when the input may be null. The CAST type strategy already derives 
the result as nullable, but CastConverter builds the RexNode from the literal 
target type. The optimizer trusts the wrong NOT NULL and can fold null checks 
away, which drops rows or produces wrong values.

h3. Reproduce

{code:java}
Table t = tEnv.fromValues(
        ROW(FIELD("i", INT())),
        Row.of((Object) null),
        Row.of(1));

t.select($("i").cast(BIGINT().notNull()).as("c"))
        .filter($("c").isNull())
        .execute()
        .print();
{code}

Expected: one row with c = NULL.
Actual: empty result. The plan collapses to an empty Values because IS NULL is 
folded to FALSE.

The same happens for a nested VARIANT input, e.g. 
parseJson(s).cast(ARRAY(VARIANT())).cast(ARRAY(INT()).notNull()). FLINK-40672 
only covered a top-level VARIANT input.

SQL is not affected. A SQL CAST cannot declare NOT NULL on the target, and 
SqlCastFunction.deriveType takes the nullability from the input.

h3. Proposed fix

CastConverter should use the resolved output type of the call, which the type 
strategy derives from the input, instead of the literal target type. This 
aligns the Table API with SQL for all casts. As a side effect, casting a NOT 
NULL input to a nullable target now yields NOT NULL, as it already does in SQL.

Also document on cast() that the top-level nullability of the target type is 
ignored.



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

Reply via email to