Fix route deletion failing due to FK constraint violations
Route deletion failed with two integrity errors: 1. route_encounters had no cascade, so SQLAlchemy tried to NULL the non-nullable route_id instead of deleting the rows 2. boss_battles.after_route_id referenced the route being deleted Added cascade="all, delete-orphan" to Route.route_encounters and nulled out boss battle after_route_id references before deletion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-h0dr
|
||||||
|
title: Fix route deletion failing due to missing cascade on route_encounters
|
||||||
|
status: completed
|
||||||
|
type: bug
|
||||||
|
priority: normal
|
||||||
|
created_at: 2026-02-14T14:19:56Z
|
||||||
|
updated_at: 2026-02-14T14:23:10Z
|
||||||
|
---
|
||||||
|
|
||||||
|
Deleting a route returns 500 due to two FK constraint issues:
|
||||||
|
|
||||||
|
1. `route_encounters.route_id` — missing cascade on the relationship (SQLAlchemy tried to NULL a NOT NULL column)
|
||||||
|
2. `boss_battles.after_route_id` — references the route being deleted
|
||||||
|
|
||||||
|
## Fix
|
||||||
|
- Added `cascade="all, delete-orphan"` to `Route.route_encounters` relationship
|
||||||
|
- Added `update(BossBattle).where(...).values(after_route_id=None)` before deleting the route in the delete endpoint
|
||||||
@@ -2,7 +2,7 @@ import json
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
from sqlalchemy import delete, select
|
from sqlalchemy import delete, select, update
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import selectinload
|
from sqlalchemy.orm import selectinload
|
||||||
|
|
||||||
@@ -373,6 +373,13 @@ async def delete_route(
|
|||||||
detail="Cannot delete route with existing encounters. Delete the encounters first.",
|
detail="Cannot delete route with existing encounters. Delete the encounters first.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Null out any boss battle references to this route
|
||||||
|
await session.execute(
|
||||||
|
update(BossBattle)
|
||||||
|
.where(BossBattle.after_route_id == route_id)
|
||||||
|
.values(after_route_id=None)
|
||||||
|
)
|
||||||
|
|
||||||
await session.delete(route)
|
await session.delete(route)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Route(Base):
|
|||||||
|
|
||||||
version_group: Mapped["VersionGroup"] = relationship(back_populates="routes")
|
version_group: Mapped["VersionGroup"] = relationship(back_populates="routes")
|
||||||
route_encounters: Mapped[list["RouteEncounter"]] = relationship(
|
route_encounters: Mapped[list["RouteEncounter"]] = relationship(
|
||||||
back_populates="route"
|
back_populates="route", cascade="all, delete-orphan"
|
||||||
)
|
)
|
||||||
encounters: Mapped[list["Encounter"]] = relationship(back_populates="route")
|
encounters: Mapped[list["Encounter"]] = relationship(back_populates="route")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user