Skip to content

[FLINK-40477][table] Fix constraint enforcer for partial deletes - #29067

Merged
fhueske merged 2 commits into
apache:masterfrom
confluentinc:fhueske-FLINK-40477-Fix-Constraint-Enforcer-for-partial-deletes
Sep 3, 2026
Merged

[FLINK-40477][table] Fix constraint enforcer for partial deletes#29067
fhueske merged 2 commits into
apache:masterfrom
confluentinc:fhueske-FLINK-40477-Fix-Constraint-Enforcer-for-partial-deletes

Conversation

@fhueske

@fhueske fhueske commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What is the purpose of the change

The sink NOT NULL enforcer inspected every row regardless of RowKind, so a by-key (partial) delete tombstone (whose non-key columns are legitimately null) was rejected (ERROR) or silently dropped (DROP), losing the delete.

This PR relaxes NOT NULL for the non-key columns of DELETE rows in key-only-delete pipelines; key columns and all other row kinds stay enforced.

Brief change log

  • pass information about partial deletes and PK to constraint checker
  • skip null checks of non-key, non-null declared columns in DELETE change records
  • add tests to validate correctness

Verifying this change

  • Added semantic tests asserting correct skipping of checks

Does this pull request potentially affect one of the following parts:

  • Dependencies (does it add or upgrade a dependency): no
  • The public API, i.e., is any changed class annotated with @Public(Evolving): no
  • The serializers: no
  • The runtime per-record code paths (performance sensitive): yes
  • Anything that affects deployment or recovery: JobManager (and its components), Checkpointing, Kubernetes/Yarn, ZooKeeper: no
  • The S3 file system connector: no

Documentation

  • Does this pull request introduce a new feature? na
  • If yes, how is the feature documented? n/a

Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: Claude Code (Opus 4.8, 1M)

The sink NOT NULL enforcer inspected every row regardless of RowKind,
so a by-key (partial) delete tombstone, whose non-key columns are legitimately null,
was rejected (ERROR) or silently dropped (DROP), losing the delete.

Relax NOT NULL for the non-key columns of DELETE rows in key-only-delete pipelines;
key columns and all other row kinds stay enforced.

Co-Generated: Claude Opus 4.8 (1M context)
@fhueske
fhueske marked this pull request as ready for review September 2, 2026 08:01
@flinkbot

flinkbot commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

CI report:

Bot commands The @flinkbot bot supports the following commands:
  • @flinkbot run azure re-run the last Azure build

@gustavodemorais gustavodemorais left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change looks easier than I expected tbh. Small blast radius and makes sense. LGTM. Only added two nits

Comment on lines +942 to +944
// Delete-by-key: a by-key delete legitimately carries null in its non-key columns ("regardless
// of nullability constraints"). The constraint enforcer only checks not-null key columns for
// by-key delete messages and ignores all value columns.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, it's a bit of a mix in the value columns/there are no guarantees. Suggestionm

Suggested change
// Delete-by-key: a by-key delete legitimately carries null in its non-key columns ("regardless
// of nullability constraints"). The constraint enforcer only checks not-null key columns for
// by-key delete messages and ignores all value columns.
// Delete-by-key: a by-key delete might carry null in its non-key columns, regardless
// of nullability constraints. The constraint enforcer should only check key columns for
// by-key delete messages and ignores all value columns.

.mapToObj(idx -> fieldNames[idx])
.toArray(String[]::new);

final Set<Integer> primaryKeySet =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rest of the class uses BitSet for the same pattern (see buildCouldPad). Suggestion: swap it instead of Set, cheaper and consistent with the file

@fhueske
fhueske merged commit d554162 into apache:master Sep 3, 2026
@fhueske
fhueske deleted the fhueske-FLINK-40477-Fix-Constraint-Enforcer-for-partial-deletes branch September 3, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants