-- +goose Up -- Apply legacy helicopter staging data into `helicopters`. -- Expected flow before this migration: -- 1) Run previous migration that creates `helicopter_old_import`. -- 2) Import old dump rows into `helicopter_old_import`. -- This migration maps old integer IDs into BINARY(16) UUIDv7-style IDs, -- then upserts into `helicopters` with `is_active` forced to 1. START TRANSACTION; -- Self-heal when staging migration is marked applied but tables were dropped/reset manually. CREATE TABLE IF NOT EXISTS helicopter_old_import ( id int(11) NOT NULL, name varchar(50) NOT NULL, type varchar(20) DEFAULT NULL, counter int(11) DEFAULT NULL, engine1 varchar(50) DEFAULT NULL, engine2 varchar(50) DEFAULT NULL, consumption double(10,2) DEFAULT NULL, service varchar(255) DEFAULT NULL, nr1 tinyint(1) DEFAULT 0, nr2 tinyint(1) DEFAULT 0, lh tinyint(1) DEFAULT 0, rh tinyint(1) DEFAULT 0, mgb tinyint(1) DEFAULT 0, igb tinyint(1) DEFAULT 0, tgb tinyint(1) DEFAULT 0, utc varchar(10) DEFAULT NULL, disabled tinyint(1) DEFAULT 0, visible tinyint(1) DEFAULT 1, dry tinyint(1) DEFAULT 0, docs text, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; CREATE TABLE IF NOT EXISTS helicopter_old_id_map ( old_id int(11) NOT NULL, new_id binary(16) NOT NULL, PRIMARY KEY (old_id), UNIQUE KEY uq_helicopter_old_id_map_new_id (new_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; INSERT INTO helicopter_old_id_map (old_id, new_id) SELECT s.id AS old_id, UNHEX(REPLACE( LOWER(CONCAT( -- UUID layout must be 8-4-4-4-12 (32 hex chars => 16 bytes). -- Put millisecond timestamp (48-bit) in first 8+4 chars for time ordering. LPAD(HEX(FLOOR(CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED) / 65536)), 8, '0'), '-', LPAD(HEX(MOD(CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED), 65536)), 4, '0'), '-', '7', LPAD(HEX(FLOOR(RAND() * 4096)), 3, '0'), '-', LPAD(HEX(FLOOR(RAND() * 16384) + 32768), 4, '0'), '-', LPAD(HEX(FLOOR(RAND() * 281474976710656)), 12, '0') )), '-', '' )) AS new_id FROM helicopter_old_import s LEFT JOIN helicopter_old_id_map m ON m.old_id = s.id WHERE m.old_id IS NULL; INSERT INTO helicopters ( id, designation, identifier, report_sequence, type, counter, engine_1, engine_2, consumption_lt_min, nr1, nr2, lh, rh, mgb, igb, tgb, utc_offset, dry, note, is_active, created_at, updated_at ) SELECT m.new_id, TRIM(s.name) AS designation, TRIM(s.name) AS identifier, 0 AS report_sequence, COALESCE(NULLIF(TRIM(s.type), ''), 'Unknown') AS type, 0 AS counter, TRIM(COALESCE(s.engine1, '')) AS engine_1, TRIM(COALESCE(s.engine2, '')) AS engine_2, COALESCE(s.consumption, 0) AS consumption_lt_min, COALESCE(s.nr1, 0) AS nr1, COALESCE(s.nr2, 0) AS nr2, COALESCE(s.lh, 0) AS lh, COALESCE(s.rh, 0) AS rh, COALESCE(s.mgb, 0) AS mgb, COALESCE(s.igb, 0) AS igb, COALESCE(s.tgb, 0) AS tgb, COALESCE(CAST(NULLIF(TRIM(s.utc), '') AS SIGNED), 0) AS utc_offset, COALESCE(s.dry, 0) AS dry, s.docs AS note, 1 AS is_active, UTC_TIMESTAMP() AS created_at, UTC_TIMESTAMP() AS updated_at FROM helicopter_old_import s JOIN helicopter_old_id_map m ON m.old_id = s.id ON DUPLICATE KEY UPDATE designation = VALUES(designation), identifier = VALUES(identifier), type = VALUES(type), engine_1 = VALUES(engine_1), engine_2 = VALUES(engine_2), consumption_lt_min = VALUES(consumption_lt_min), nr1 = VALUES(nr1), nr2 = VALUES(nr2), lh = VALUES(lh), rh = VALUES(rh), mgb = VALUES(mgb), igb = VALUES(igb), tgb = VALUES(tgb), utc_offset = VALUES(utc_offset), dry = VALUES(dry), note = VALUES(note), is_active = 1, updated_at = UTC_TIMESTAMP(); COMMIT; -- +goose Down -- Data migration is intentionally non-reversible. -- Keep imported data and ID mapping as audit trail. SELECT 1;