-- ============================================================================ -- Production migration: apikey.alias (unique) + markdown/patch authorship -- ============================================================================ -- Idempotent. Safe to run multiple times. Target: MySQL 8 (no native -- ADD COLUMN IF NOT EXISTS, so columns are guarded via information_schema -- + a prepared statement). Mirrors the app's db.run_migrations(); running -- both is harmless. -- -- Apply against the application schema, e.g.: -- docker exec -i mysql sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" hangmanlab' \ -- < 2026-05-16_apikey_alias_authorship.sql -- ============================================================================ SET @schema := DATABASE(); -- ---- helper macro is not available in plain SQL; repeat the guarded block -- -- apikey.alias -------------------------------------------------------------- SET @c := (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=@schema AND table_name='apikey' AND column_name='alias'); SET @ddl := IF(@c=0, 'ALTER TABLE apikey ADD COLUMN alias VARCHAR(255) NULL', 'DO 0'); PREPARE st FROM @ddl; EXECUTE st; DEALLOCATE PREPARE st; -- backfill: existing keys get alias = their (unique) key string UPDATE apikey SET alias = `key` WHERE alias IS NULL; -- apikey unique constraint on alias ----------------------------------------- SET @i := (SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema=@schema AND table_name='apikey' AND index_name='uq_apikey_alias'); SET @ddl := IF(@i=0, 'ALTER TABLE apikey ADD CONSTRAINT uq_apikey_alias UNIQUE (alias)', 'DO 0'); PREPARE st FROM @ddl; EXECUTE st; DEALLOCATE PREPARE st; -- markdown.updated_at ------------------------------------------------------- SET @c := (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=@schema AND table_name='markdown' AND column_name='updated_at'); SET @ddl := IF(@c=0, 'ALTER TABLE markdown ADD COLUMN updated_at DATETIME NULL', 'DO 0'); PREPARE st FROM @ddl; EXECUTE st; DEALLOCATE PREPARE st; UPDATE markdown SET updated_at = created_at WHERE updated_at IS NULL; -- markdown.author ----------------------------------------------------------- SET @c := (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=@schema AND table_name='markdown' AND column_name='author'); SET @ddl := IF(@c=0, 'ALTER TABLE markdown ADD COLUMN author VARCHAR(255) NULL', 'DO 0'); PREPARE st FROM @ddl; EXECUTE st; DEALLOCATE PREPARE st; UPDATE markdown SET author = 'admin' WHERE author IS NULL; -- markdown.last_modified_by ------------------------------------------------- SET @c := (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=@schema AND table_name='markdown' AND column_name='last_modified_by'); SET @ddl := IF(@c=0, 'ALTER TABLE markdown ADD COLUMN last_modified_by VARCHAR(255) NULL', 'DO 0'); PREPARE st FROM @ddl; EXECUTE st; DEALLOCATE PREPARE st; UPDATE markdown SET last_modified_by = 'admin' WHERE last_modified_by IS NULL; -- markdown_patch.author ----------------------------------------------------- SET @c := (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=@schema AND table_name='markdown_patch' AND column_name='author'); SET @ddl := IF(@c=0, 'ALTER TABLE markdown_patch ADD COLUMN author VARCHAR(255) NULL', 'DO 0'); PREPARE st FROM @ddl; EXECUTE st; DEALLOCATE PREPARE st; UPDATE markdown_patch SET author = 'admin' WHERE author IS NULL; -- markdown_patch.last_modified_by ------------------------------------------- SET @c := (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=@schema AND table_name='markdown_patch' AND column_name='last_modified_by'); SET @ddl := IF(@c=0, 'ALTER TABLE markdown_patch ADD COLUMN last_modified_by VARCHAR(255) NULL', 'DO 0'); PREPARE st FROM @ddl; EXECUTE st; DEALLOCATE PREPARE st; UPDATE markdown_patch SET last_modified_by = 'admin' WHERE last_modified_by IS NULL;