diff --git a/backend/alembic/versions/0007_indizes_und_unique_constraints.py b/backend/alembic/versions/0007_indizes_und_unique_constraints.py index 2d2672c..c9efa97 100644 --- a/backend/alembic/versions/0007_indizes_und_unique_constraints.py +++ b/backend/alembic/versions/0007_indizes_und_unique_constraints.py @@ -11,6 +11,11 @@ Zwei unabhängige Fixes aus dem Agenten-Review dieser Session: fängt die resultierende IntegrityError bereits ab (lifecycle.py, mindermenge.py). 2. Fehlende Indizes auf häufig gefilterten Fremdschlüsseln (Eskalations-Cron, Kontroll-Sperre-Check, Dashboard-Ablaufdatum-Abfrage u.a.). + +Ein op.execute() pro Statement (nicht mehrere per Semikolon gebündelt) - der +asyncpg-Treiber lehnt mehrere Kommandos in einem prepared statement ab +("cannot insert multiple commands into a prepared statement", Fund beim +echten Deploy-Lauf gegen die Live-DB). """ from typing import Sequence, Union @@ -21,43 +26,44 @@ down_revision: Union[str, None] = "0006_add_eskalation_felder" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None +_UPGRADE_STATEMENTS = [ + "CREATE UNIQUE INDEX idx_kontrolle_eine_aktive_je_objekt " + "ON kontrolle (objekt_id) WHERE status = 'in_bearbeitung'", + "CREATE UNIQUE INDEX idx_mindermenge_eine_aktive_je_fehlbestand " + "ON mindermengen_genehmigung (fehlbestand_id) WHERE status = 'aktiv'", + "CREATE INDEX idx_fehlbestand_material ON fehlbestand (material_id)", + "CREATE INDEX idx_fehlbestand_status_entstanden ON fehlbestand (status, entstanden_am)", + "CREATE INDEX idx_kontrolle_objekt_status ON kontrolle (objekt_id, status)", + "CREATE INDEX idx_kontrollposition_kontrolle ON kontrollposition (kontrolle_id)", + "CREATE INDEX idx_zustaendigkeit_objekt ON zustaendigkeit (objekt_id)", + "CREATE INDEX idx_zustaendigkeit_standort ON zustaendigkeit (standort_id)", + "CREATE INDEX idx_benutzer_rolle_rolle ON benutzer_rolle (rolle)", + "CREATE INDEX idx_objektposition_material ON objektposition (material_id)", + "CREATE INDEX idx_nachfuellung_fehlbestand ON nachfuellung (fehlbestand_id)", + "CREATE INDEX idx_objektposition_ablauf ON objektposition (ablaufdatum) WHERE ablaufdatum IS NOT NULL", +] + +_INDEX_NAMEN_ABWAERTS = [ + "idx_objektposition_ablauf", + "idx_nachfuellung_fehlbestand", + "idx_objektposition_material", + "idx_benutzer_rolle_rolle", + "idx_zustaendigkeit_standort", + "idx_zustaendigkeit_objekt", + "idx_kontrollposition_kontrolle", + "idx_kontrolle_objekt_status", + "idx_fehlbestand_status_entstanden", + "idx_fehlbestand_material", + "idx_mindermenge_eine_aktive_je_fehlbestand", + "idx_kontrolle_eine_aktive_je_objekt", +] + def upgrade() -> None: - op.execute( - """ - CREATE UNIQUE INDEX idx_kontrolle_eine_aktive_je_objekt - ON kontrolle (objekt_id) WHERE status = 'in_bearbeitung'; - CREATE UNIQUE INDEX idx_mindermenge_eine_aktive_je_fehlbestand - ON mindermengen_genehmigung (fehlbestand_id) WHERE status = 'aktiv'; - - CREATE INDEX idx_fehlbestand_material ON fehlbestand (material_id); - CREATE INDEX idx_fehlbestand_status_entstanden ON fehlbestand (status, entstanden_am); - CREATE INDEX idx_kontrolle_objekt_status ON kontrolle (objekt_id, status); - CREATE INDEX idx_kontrollposition_kontrolle ON kontrollposition (kontrolle_id); - CREATE INDEX idx_zustaendigkeit_objekt ON zustaendigkeit (objekt_id); - CREATE INDEX idx_zustaendigkeit_standort ON zustaendigkeit (standort_id); - CREATE INDEX idx_benutzer_rolle_rolle ON benutzer_rolle (rolle); - CREATE INDEX idx_objektposition_material ON objektposition (material_id); - CREATE INDEX idx_nachfuellung_fehlbestand ON nachfuellung (fehlbestand_id); - CREATE INDEX idx_objektposition_ablauf ON objektposition (ablaufdatum) WHERE ablaufdatum IS NOT NULL; - """ - ) + for statement in _UPGRADE_STATEMENTS: + op.execute(statement) def downgrade() -> None: - op.execute( - """ - DROP INDEX idx_objektposition_ablauf; - DROP INDEX idx_nachfuellung_fehlbestand; - DROP INDEX idx_objektposition_material; - DROP INDEX idx_benutzer_rolle_rolle; - DROP INDEX idx_zustaendigkeit_standort; - DROP INDEX idx_zustaendigkeit_objekt; - DROP INDEX idx_kontrollposition_kontrolle; - DROP INDEX idx_kontrolle_objekt_status; - DROP INDEX idx_fehlbestand_status_entstanden; - DROP INDEX idx_fehlbestand_material; - DROP INDEX idx_mindermenge_eine_aktive_je_fehlbestand; - DROP INDEX idx_kontrolle_eine_aktive_je_objekt; - """ - ) + for name in _INDEX_NAMEN_ABWAERTS: + op.execute(f"DROP INDEX {name}")