"""Fahrzeug/Anhänger-Kopplung: objekt.gezogen_von_objekt_id (additiv) Revision ID: 0009_gezogen_von Revises: 0008_geraet_instanz Create Date: 2026-09-04 Nutzer-Vorgabe: Fahrzeuge und Anhänger sollen beide als eigenständige Objekte gehen (unabhängig, kein Zwang) UND optional fest gekoppelt werden können (Anhänger gehört zu einem Zugfahrzeug). Selbstreferenzierende, nullable FK - kein eigener Anhänger-Objekttyp/-Tabelle nötig, Objekt bleibt generisch (Karte 11). """ from typing import Sequence, Union from alembic import op revision: str = "0009_gezogen_von" down_revision: Union[str, None] = "0008_geraet_instanz" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.execute( "ALTER TABLE objekt ADD COLUMN gezogen_von_objekt_id INTEGER " "REFERENCES objekt(id) ON DELETE SET NULL" ) op.execute("CREATE INDEX idx_objekt_gezogen_von ON objekt (gezogen_von_objekt_id)") # postgres-expert-Review-Fund: DB-Sicherheitsnetz gegen Selbstbezug (Objekt # zieht sich selbst) - Anwendungscode prüft zusätzlich direkte Zyklen (A↔B), # mehrstufige Ketten sind fachlich nicht vorgesehen und bewusst nicht per DB # erzwungen (Aufwand/Nutzen). op.execute( "ALTER TABLE objekt ADD CONSTRAINT objekt_kein_selbstbezug " "CHECK (gezogen_von_objekt_id IS DISTINCT FROM id)" ) def downgrade() -> None: op.execute("ALTER TABLE objekt DROP CONSTRAINT objekt_kein_selbstbezug") op.execute("DROP INDEX idx_objekt_gezogen_von") op.execute("ALTER TABLE objekt DROP COLUMN gezogen_von_objekt_id")