[DB] Fehlende Unique Constraints erlauben doppelte Essensplaene und Eintraege #46

Closed
opened 2026-09-09 20:17:00 +00:00 by Aceless · 1 comment
Owner

Problem

backend/database_definition.sql kennt weder

  • weekly_meal_plan (space_id, week_start) noch
  • meal_plan_entry (meal_plan_id, date, meal_type)

als eindeutig. Beide Regeln werden nur im Anwendungscode geprueft (MealPlansController.CreateWeeklyMealPlan, MealPlanEntriesController.AddEntry) und dort jeweils als Check-Then-Act ohne Sperre.

Auswirkung

Sind erst einmal Duplikate in der Tabelle, wirft GetWeeklyMealPlan beim Lesen eine Exception, weil QuerySingleOrDefaultAsync bei mehr als einer Zeile fehlschlaegt. Der Space ist damit nicht mehr benutzbar. Der Commit "fixed creating double mealplan" hat das Symptom in der Anwendungsschicht entschaerft, die Ursache bleibt.

Fix

ALTER TABLE weekly_meal_plan
  ADD CONSTRAINT weekly_meal_plan_space_week_key UNIQUE (space_id, week_start);

ALTER TABLE meal_plan_entry
  ADD CONSTRAINT meal_plan_entry_slot_key UNIQUE (meal_plan_id, date, meal_type);

Vorher vorhandene Duplikate bereinigen. Im Code INSERT ... ON CONFLICT ... DO NOTHING RETURNING * verwenden.

Ergaenzend fehlt ein CHECK, dass recipe_id oder custom_meal gesetzt ist.

## Problem `backend/database_definition.sql` kennt weder - `weekly_meal_plan (space_id, week_start)` noch - `meal_plan_entry (meal_plan_id, date, meal_type)` als eindeutig. Beide Regeln werden nur im Anwendungscode geprueft (`MealPlansController.CreateWeeklyMealPlan`, `MealPlanEntriesController.AddEntry`) und dort jeweils als Check-Then-Act ohne Sperre. ## Auswirkung Sind erst einmal Duplikate in der Tabelle, wirft `GetWeeklyMealPlan` beim Lesen eine Exception, weil `QuerySingleOrDefaultAsync` bei mehr als einer Zeile fehlschlaegt. Der Space ist damit nicht mehr benutzbar. Der Commit "fixed creating double mealplan" hat das Symptom in der Anwendungsschicht entschaerft, die Ursache bleibt. ## Fix ```sql ALTER TABLE weekly_meal_plan ADD CONSTRAINT weekly_meal_plan_space_week_key UNIQUE (space_id, week_start); ALTER TABLE meal_plan_entry ADD CONSTRAINT meal_plan_entry_slot_key UNIQUE (meal_plan_id, date, meal_type); ``` Vorher vorhandene Duplikate bereinigen. Im Code `INSERT ... ON CONFLICT ... DO NOTHING RETURNING *` verwenden. Ergaenzend fehlt ein CHECK, dass `recipe_id` oder `custom_meal` gesetzt ist.
Author
Owner

Erledigt in backend/migrations/001_constraints_and_indexes.sql.

  • Duplikate werden vorher bereinigt: doppelte Slots werden entfernt, Einträge doppelter Wochenpläne auf den ältesten Plan umgehängt, sofern der Slot dort frei ist.
  • weekly_meal_plan_space_week_key UNIQUE (space_id, week_start)
  • meal_plan_entry_slot_key UNIQUE (meal_plan_id, date, meal_type)
  • meal_plan_entry_content_check CHECK (recipe_id IS NOT NULL OR custom_meal IS NOT NULL), als NOT VALID angelegt, damit vorhandene Zeilen die Migration nicht blockieren.

Der Code nutzt diese Constraints über ON CONFLICT. Die Migration muss vor dem Deployment eingespielt werden.

Geprüft: Migration auf einer frischen PostgreSQL-16-Datenbank eingespielt, Constraints sind vorhanden, doppelter Wochenplan liefert denselben Plan zurück, doppelter Eintrag 409.


Branch backend/issue-fixes, Commits 90183ae.

Erledigt in `backend/migrations/001_constraints_and_indexes.sql`. - Duplikate werden vorher bereinigt: doppelte Slots werden entfernt, Einträge doppelter Wochenpläne auf den ältesten Plan umgehängt, sofern der Slot dort frei ist. - `weekly_meal_plan_space_week_key UNIQUE (space_id, week_start)` - `meal_plan_entry_slot_key UNIQUE (meal_plan_id, date, meal_type)` - `meal_plan_entry_content_check CHECK (recipe_id IS NOT NULL OR custom_meal IS NOT NULL)`, als `NOT VALID` angelegt, damit vorhandene Zeilen die Migration nicht blockieren. Der Code nutzt diese Constraints über `ON CONFLICT`. **Die Migration muss vor dem Deployment eingespielt werden.** **Geprüft:** Migration auf einer frischen PostgreSQL-16-Datenbank eingespielt, Constraints sind vorhanden, doppelter Wochenplan liefert denselben Plan zurück, doppelter Eintrag 409. --- Branch `backend/issue-fixes`, Commits 90183ae.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Aceless/RecipePlanner#46
No description provided.