/** * Normalize legacy Lorcana set_code values and scryfall_id (external id) shapes * so bulk import from lorcana-api.com upserts cleanly instead of inserting duplicates. * * Legacy imports used numeric set codes (1/2/3) or lowercase abbreviations (tfc/rotf/ink). * The bulk API uses Set_ID values TFC, ROF, INK, etc., and Unique_ID like TFC-001. */ export const shorthands = undefined; export const up = (pgm) => { pgm.sql(` UPDATE cards SET game = 'Lorcana' WHERE game ILIKE 'lorcana' AND game <> 'Lorcana'; UPDATE cards SET set_code = 'TFC', set_name = 'The First Chapter' WHERE game = 'Lorcana' AND set_code IN ('1', 'tfc', 'TFC'); UPDATE cards SET set_code = 'ROF', set_name = 'Rise of the Floodborn' WHERE game = 'Lorcana' AND set_code IN ('2', 'rotf', 'ROF'); UPDATE cards SET set_code = 'INK', set_name = 'Into the Inklands' WHERE game = 'Lorcana' AND set_code IN ('3', 'ink', 'INK', 'ITI'); UPDATE cards SET set_code = 'TFC', set_name = 'The First Chapter' WHERE game = 'Lorcana' AND set_code IS NULL AND set_name ILIKE '%first chapter%'; UPDATE cards SET set_code = 'ROF', set_name = 'Rise of the Floodborn' WHERE game = 'Lorcana' AND set_code IS NULL AND set_name ILIKE '%rise of the floodborn%'; UPDATE cards SET set_code = 'INK', set_name = 'Into the Inklands' WHERE game = 'Lorcana' AND set_code IS NULL AND set_name ILIKE '%into the inklands%'; `); // Drop legacy duplicate rows when the canonical Unique_ID row already exists. pgm.sql(` DELETE FROM cards AS dup WHERE dup.game = 'Lorcana' AND dup.set_code IS NOT NULL AND TRIM(dup.card_number) <> '' AND dup.scryfall_id IS DISTINCT FROM ( dup.set_code || '-' || LPAD( REGEXP_REPLACE(TRIM(dup.card_number), '/.*$', ''), 3, '0' ) ) AND EXISTS ( SELECT 1 FROM cards AS keeper WHERE keeper.scryfall_id = dup.set_code || '-' || LPAD( REGEXP_REPLACE(TRIM(dup.card_number), '/.*$', ''), 3, '0' ) ); `); // Keep one row per set + collector number before scryfall_id unification. pgm.sql(` DELETE FROM cards AS dup WHERE dup.game = 'Lorcana' AND dup.set_code IS NOT NULL AND TRIM(dup.card_number) <> '' AND dup.id <> ( SELECT MIN(peer.id) FROM cards AS peer WHERE peer.game = 'Lorcana' AND peer.set_code = dup.set_code AND REGEXP_REPLACE(TRIM(peer.card_number), '/.*$', '') = REGEXP_REPLACE(TRIM(dup.card_number), '/.*$', '') ); `); // Unify remaining legacy scryfall_id values to Unique_ID shape (SET-NNN). pgm.sql(` UPDATE cards AS c SET scryfall_id = c.set_code || '-' || LPAD( REGEXP_REPLACE(TRIM(c.card_number), '/.*$', ''), 3, '0' ) WHERE c.game = 'Lorcana' AND c.set_code IS NOT NULL AND TRIM(c.card_number) <> '' AND c.scryfall_id IS DISTINCT FROM ( c.set_code || '-' || LPAD( REGEXP_REPLACE(TRIM(c.card_number), '/.*$', ''), 3, '0' ) ) AND NOT EXISTS ( SELECT 1 FROM cards AS other WHERE other.scryfall_id = c.set_code || '-' || LPAD( REGEXP_REPLACE(TRIM(c.card_number), '/.*$', ''), 3, '0' ) ); `); }; export const down = () => { throw new Error('Irreversible data migration'); };