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

ASF GitHub Bot updated FLINK-40477:
-----------------------------------
    Labels: pull-request-available  (was: )

> Partial deletes fail sink NOT NULL enforcement
> ----------------------------------------------
>
>                 Key: FLINK-40477
>                 URL: https://issues.apache.org/jira/browse/FLINK-40477
>             Project: Flink
>          Issue Type: Bug
>          Components: Table SQL / Runtime
>    Affects Versions: 2.3.0
>            Reporter: Fabian Hueske
>            Assignee: Fabian Hueske
>            Priority: Critical
>              Labels: pull-request-available
>
> In a partial-delete (key-only) pipeline, a -D tombstone carries the key and 
> sets all non-key columns to null, "regardless of nullability constraints" 
> (see ChangelogFunction / ChangelogMode#keyOnlyDeletes).
> When the sink has a NOT NULL value (non-key) column, the sink constraint 
> enforcer (NotNullConstraint) inspects the tombstone and reacts to that null:
>  * table.exec.sink.not-null-enforcer = ERROR (default): throws 
> EnforcerException → the job fails on every by-key delete (crash-restart loop).
>  * table.exec.sink.not-null-enforcer = DROP: the tombstone is silently 
> dropped → the row is never deleted (stale data, no error).
> Root cause: NotNullConstraint#enforce (module flink-table-runtime, package 
> ...operators.sink.constraint) checks input.isNullAt(index) for every row 
> regardless of RowKind; it has no notion that a DELETE in a key-only-delete 
> pipeline legitimately carries null non-key columns.
> This is distinct from FLINK-40468 (composite serializer NPE): that requires a 
> null nested inside a composite constructor, whereas this affects any NOT NULL 
> top-level value column and is caught earlier, at the enforcer.
> How to reproduce (scalar INT column, so no composite/serializer path is 
> involved):
>  
> {code:java}
> -- source produces key-only deletes; sink accepts key-only deletes
> CREATE TABLE src (id INT PRIMARY KEY NOT ENFORCED, v INT NOT NULL) WITH (
>   'connector' = 'values', 
>   'changelog-mode' = 'I,UA,D',
>   'source.produces-delete-by-key' = 'true', ...);                             
> CREATE TABLE snk (id INT PRIMARY KEY NOT ENFORCED, v INT NOT NULL) WITH (
>   'connector' = 'values', 'sink-insert-only' = 'false',
>   'sink.supports-delete-by-key' = 'true');
> INSERT INTO snk SELECT id, v FROM src;
> -- Source data: +I(1, 10), +I(2, 20), -D(1, null) (tombstone: key only, v 
> null).               {code}
>  
>  * Expected: the tombstone is applied by key; final sink state is \{(2, 20)}.
>  * Actual (ERROR): EnforcerException: Column 'v' is NOT NULL, however, a null 
> value is being written into it.
>  * Actual (DROP): tombstone dropped; final sink state is \{(1, 10), (2, 20)} 
> (stale row 1).
> Suggested fix: make the enforcer skip the NOT NULL check for the non-key 
> columns of a DELETE row when the input is a key-only-delete pipeline 
> (ChangelogMode#keyOnlyDeletes). Key columns and non-DELETE rows stay fully 
> enforced; full-delete pipelines are unaffected.
>  



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

Reply via email to