Skip to content

OnDeleteType Literal is missing SET DEFAULT and NO ACTION — rejects valid SQL referential actions #1836

@mahdirajaee

Description

@mahdirajaee

Description

The OnDeleteType type alias in sqlmodel/main.py (line 91) is defined as:

OnDeleteType = Literal["CASCADE", "SET NULL", "RESTRICT"]

The SQL standard defines 5 referential actions for ON DELETE / ON UPDATE:

  1. CASCADE
  2. SET NULL
  3. SET DEFAULT
  4. RESTRICT
  5. NO ACTION

SQLAlchemy's ForeignKey(ondelete=...) accepts any string and its documentation explicitly lists all 5 as valid values.

Impact

  • NO ACTION is the default behavior in PostgreSQL and most databases. Developers who want to be explicit in their schema (common in migration-driven workflows with Alembic) cannot express this without type errors.
  • SET DEFAULT is used when a foreign key column has a server_default and the parent row is deleted. This is supported by PostgreSQL, MySQL, and SQLite.

A developer hitting this gets a confusing mypy/pyright error on a perfectly valid schema definition. The only workarounds are casting to Any or dropping down to sa_column.

Fix

OnDeleteType = Literal["CASCADE", "SET NULL", "SET DEFAULT", "RESTRICT", "NO ACTION"]

One-line change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions