diff --git a/sqlmodel/main.py b/sqlmodel/main.py index c551afea36..3ff3a97232 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -87,7 +87,7 @@ | Mapping[int, Union["IncEx", bool]] | Mapping[str, Union["IncEx", bool]] ) -OnDeleteType = Literal["CASCADE", "SET NULL", "RESTRICT"] +OnDeleteType = Literal["CASCADE", "SET NULL", "SET DEFAULT", "RESTRICT", "NO ACTION"] def __dataclass_transform__( diff --git a/tests/test_main.py b/tests/test_main.py index fa40b71853..0ca1fe9e5a 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -3,6 +3,7 @@ import pytest from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import RelationshipProperty +from sqlalchemy.schema import CreateTable from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select @@ -216,3 +217,26 @@ class Hero(SQLModel, table=True): assert len(foreign_keys) == 1 assert foreign_keys[0].ondelete == "CASCADE" assert team_id_column.nullable is False + + +@pytest.mark.parametrize("ondelete", ["SET DEFAULT", "NO ACTION"]) +def test_foreign_key_ondelete_referential_actions(clear_sqlmodel, ondelete): + class Team(SQLModel, table=True): + id: int | None = Field(default=None, primary_key=True) + + class Hero(SQLModel, table=True): + id: int | None = Field(default=None, primary_key=True) + team_id: int | None = Field( + default=None, foreign_key="team.id", ondelete=ondelete + ) + + engine = create_engine("sqlite://") + SQLModel.metadata.create_all(engine) + + hero_table = Hero.__table__ # type: ignore[attr-defined] + foreign_keys = list(hero_table.c.team_id.foreign_keys) + assert len(foreign_keys) == 1 + assert foreign_keys[0].ondelete == ondelete + + ddl = str(CreateTable(hero_table).compile(engine)) + assert f"ON DELETE {ondelete}" in ddl