Skip to content

linter: add ban-set-null-on-not-null-column rule - #1420

Open
MankhongGarden wants to merge 1 commit into
sbdchd:masterfrom
MankhongGarden:ban-set-null-on-not-null-column
Open

MankhongGarden wants to merge 1 commit into
sbdchd:masterfrom
MankhongGarden:ban-set-null-on-not-null-column

Conversation

@MankhongGarden

Copy link
Copy Markdown

Fixes #1136

Adds ban-set-null-on-not-null-column (enabled by default). It warns when a foreign key uses ON DELETE SET NULL or ON UPDATE SET NULL on a column that is NOT NULL, since deleting/updating a referenced row then fails with a not-null violation.

What it catches (within one file)

  • create table with a NOT NULL column and a column-level references ... on delete set null or a table-level foreign key (...) ... on delete set null
  • primary key columns (column-level or primary key (...)), since they're implicitly NOT NULL
  • on update set null, same as on delete set null
  • on delete set null (col, ...): only the listed columns are checked
  • alter table ... add column ... not null references ... on delete set null
  • alter table ... add constraint ... foreign key ... on delete set null on a column already known to be NOT NULL (from create table, add column, or alter column ... set not null)
  • alter column ... set not null on a column that already has a SET NULL foreign key in the file. This one is reported on the set not null statement.

State is reset by drop not null, drop constraint <fk name>, drop table, and re-creating the table.

What it doesn't catch

  • NOT NULL constraints from earlier migration files. Squawk only sees the current file.
  • Table names are matched as written, so messages and public.messages are treated as different tables.
  • NOT NULL that comes from domains, CHECK (col IS NOT NULL), LIKE/INHERITS/PARTITION OF, or ADD PRIMARY KEY USING INDEX.

Testing

  • cargo insta test -p squawk-linter --check --unreferenced reject: 17 new tests (10 snapshot error cases, 7 ok cases). All squawk-linter tests pass except ignore::test::starting_line_aka_zero, which fails on Windows on unmodified master too (the fix emits \r\n, but the snapshot expects \n).
  • cargo clippy -p squawk-linter --all-targets --all-features -- -D warnings: clean
  • cargo fmt -- --check: clean

I only ran these locally on Windows with the GNU toolchain. I couldn't build crates that depend on mimalloc (squawk, squawk-server, squawk-wasm, xtask) because there's no C compiler on that machine. So I added the rule stubs by hand, following what cargo xtask new-rule generates, and I haven't run workspace-wide cargo clippy/cargo check. CI should cover those. No other crate's test inputs contain SET NULL, so I don't expect any other snapshots to change.

@netlify

netlify Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

👷 Deploy request for squawkhq pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 6a6e87f

@sbdchd

sbdchd commented Oct 19, 2026

Copy link
Copy Markdown
Owner

How often do you have the foreign key part in the same file as the part that creates the original table?

I'm wondering if we need a more fully featured semantic model to support this

@MankhongGarden

Copy link
Copy Markdown
Author

Good question. From what I've seen, the most common case is a single migration that creates a new table together with its foreign keys, like the example in #1136. The NOT NULL and the SET NULL are written a few lines apart in the same create table, so a per-file check catches it.

The case it misses is a later migration that adds a SET NULL foreign key (or set not null) to a column whose NOT NULL was set in an earlier file. Catching that would need the schema from earlier migrations, which I think is the semantic model you mean.

adding-not-null-field already tracks state within one file in a similar way, so I kept this rule to the same scope. If you'd prefer to wait for a fuller model, I'm happy to rework it on top of that later, or to narrow this PR to just the create table case for now.

Warn when a foreign key uses `ON DELETE SET NULL` / `ON UPDATE SET NULL`
on a column that is `NOT NULL` (including primary key columns) in the
same file, since deleting/updating a referenced row will then fail.

rel: sbdchd#1136
@MankhongGarden
MankhongGarden force-pushed the ban-set-null-on-not-null-column branch from 3d0f058 to 6a6e87f Compare October 26, 2026 18:32

This branch has not been deployed

No deployments
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.

New rule: warn when ON DELETE SET NULL targets a NOT NULL column

2 participants