-- profile.id's CHECK(id = 1) singleton constraint (migration 0003) can't be -- dropped via ALTER TABLE -- SQLite has no DROP CONSTRAINT -- so this -- rebuilds the table via SQLite's documented rename/recreate/copy/drop -- pattern instead. Always create the replacement under a different name and -- RENAME it into place at the end (never rename the live table away first) -- -- verified directly against SQLite that this ordering is what keeps -- other tables' foreign keys intact when they exist (not the case for -- profile, but kept consistent with migrations 0024/0025 for the same -- pattern). user_id is nullable for the same not-yet-known-owner reason as -- migration 0022 -- see its comment. CREATE TABLE profile_new ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER REFERENCES users(id), name TEXT NOT NULL DEFAULT 'Default', garmin_email TEXT NOT NULL DEFAULT '', garmin_password TEXT NOT NULL DEFAULT '', rolling_window_days INTEGER NOT NULL DEFAULT 90, backfill_horizon_days INTEGER NOT NULL DEFAULT 1095, max_heart_rate REAL, resting_heart_rate REAL, hr_zone1_min_pct REAL NOT NULL DEFAULT 50, hr_zone1_max_pct REAL NOT NULL DEFAULT 60, hr_zone2_min_pct REAL NOT NULL DEFAULT 60, hr_zone2_max_pct REAL NOT NULL DEFAULT 70, hr_zone3_min_pct REAL NOT NULL DEFAULT 70, hr_zone3_max_pct REAL NOT NULL DEFAULT 80, hr_zone4_min_pct REAL NOT NULL DEFAULT 80, hr_zone4_max_pct REAL NOT NULL DEFAULT 90, hr_zone5_min_pct REAL NOT NULL DEFAULT 90, hr_zone5_max_pct REAL NOT NULL DEFAULT 100, warmup_minutes REAL NOT NULL DEFAULT 10, cooldown_minutes REAL NOT NULL DEFAULT 5, min_representative_pace_sec_per_km REAL NOT NULL DEFAULT 720, min_representative_time_seconds REAL NOT NULL DEFAULT 3, pace_color TEXT NOT NULL DEFAULT '#3b82f6', heart_rate_color TEXT NOT NULL DEFAULT '#ef4444', warmup_color TEXT NOT NULL DEFAULT '#c2410c', effort_color TEXT NOT NULL DEFAULT '#7c3aed', recovery_color TEXT NOT NULL DEFAULT '#15803d', cooldown_color TEXT NOT NULL DEFAULT '#fb923c', main_line_tint_pct REAL NOT NULL DEFAULT 20, background_darken_pct REAL NOT NULL DEFAULT 35, target_brighten_pct REAL NOT NULL DEFAULT 20, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')), UNIQUE(user_id) ); INSERT INTO profile_new ( id, user_id, name, garmin_email, garmin_password, rolling_window_days, backfill_horizon_days, max_heart_rate, resting_heart_rate, hr_zone1_min_pct, hr_zone1_max_pct, hr_zone2_min_pct, hr_zone2_max_pct, hr_zone3_min_pct, hr_zone3_max_pct, hr_zone4_min_pct, hr_zone4_max_pct, hr_zone5_min_pct, hr_zone5_max_pct, warmup_minutes, cooldown_minutes, min_representative_pace_sec_per_km, min_representative_time_seconds, pace_color, heart_rate_color, warmup_color, effort_color, recovery_color, cooldown_color, main_line_tint_pct, background_darken_pct, target_brighten_pct, created_at, updated_at ) SELECT id, NULL, name, garmin_email, garmin_password, rolling_window_days, backfill_horizon_days, max_heart_rate, resting_heart_rate, hr_zone1_min_pct, hr_zone1_max_pct, hr_zone2_min_pct, hr_zone2_max_pct, hr_zone3_min_pct, hr_zone3_max_pct, hr_zone4_min_pct, hr_zone4_max_pct, hr_zone5_min_pct, hr_zone5_max_pct, warmup_minutes, cooldown_minutes, min_representative_pace_sec_per_km, min_representative_time_seconds, pace_color, heart_rate_color, warmup_color, effort_color, recovery_color, cooldown_color, main_line_tint_pct, background_darken_pct, target_brighten_pct, created_at, updated_at FROM profile; DROP TABLE profile; ALTER TABLE profile_new RENAME TO profile;