-- ============================================ -- Cleanup Orphaned Mission Calendars -- ============================================ -- This script removes calendars that are linked to deleted missions -- (calendars with name starting with "Mission: " but missionId is NULL) -- -- WARNING: This will delete calendars and their events! -- Review the calendars first before running the DELETE statements. -- -- Usage: -- docker-compose -f docker-compose.prod.yml --env-file .env.production exec db psql -U neah_user -d calendar_db -f /path/to/cleanup-orphaned-mission-calendars.sql -- OR -- psql -U neah_user -d calendar_db < cleanup-orphaned-mission-calendars.sql -- Step 1: Review what will be deleted (run this first!) SELECT c.id, c.name, c."missionId", c."userId", u.email as user_email, COUNT(e.id) as event_count FROM "Calendar" c LEFT JOIN "User" u ON c."userId" = u.id LEFT JOIN "Event" e ON e."calendarId" = c.id WHERE c.name LIKE 'Mission: %' AND c."missionId" IS NULL GROUP BY c.id, c.name, c."missionId", c."userId", u.email ORDER BY event_count DESC, c.name; -- Step 2: Check total counts SELECT COUNT(*) as orphaned_calendars, SUM((SELECT COUNT(*) FROM "Event" WHERE "calendarId" = c.id)) as total_events FROM "Calendar" c WHERE c.name LIKE 'Mission: %' AND c."missionId" IS NULL; -- Step 3: Delete events from orphaned calendars (events will be cascade deleted, but this is explicit) -- Events are automatically deleted when calendars are deleted due to CASCADE, -- but we can delete them first if you want to see the progress DELETE FROM "Event" WHERE "calendarId" IN ( SELECT id FROM "Calendar" WHERE name LIKE 'Mission: %' AND "missionId" IS NULL ); -- Step 4: Delete orphaned mission calendars -- UNCOMMENT THE LINE BELOW AFTER REVIEWING THE RESULTS FROM STEP 1 -- DELETE FROM "Calendar" -- WHERE name LIKE 'Mission: %' -- AND "missionId" IS NULL; -- Step 5: Verify cleanup (run after deletion) SELECT COUNT(*) as remaining_orphaned_calendars FROM "Calendar" WHERE name LIKE 'Mission: %' AND "missionId" IS NULL;