exports.up = async function(knex) { const duplicates = await knex.raw(` SELECT actor_id, platform, lower(handle) AS handle_lower, COUNT(*) AS count FROM actors_socials WHERE handle IS NOT NULL GROUP BY actor_id, platform, lower(handle) HAVING COUNT(*) > 1 `); if (duplicates.rows.length > 0) { console.log(`Deduping ${duplicates.rows.length} actors_socials handle group(s)`, duplicates.rows.map((row) => `${row.actor_id}/${row.platform}/${row.handle_lower} (${row.count})`).join(', ')); } await knex.raw(` DELETE FROM actors_socials WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( PARTITION BY actor_id, platform, lower(handle) ORDER BY (handle = lower(handle)) ASC, created_at ASC ) AS rn FROM actors_socials WHERE handle IS NOT NULL ) ranked WHERE rn > 1 ); ALTER TABLE actors_socials DROP CONSTRAINT actors_social_actor_id_platform_handle_unique; CREATE UNIQUE INDEX actors_socials_actor_id_platform_handle_lower_unique ON actors_socials (actor_id, platform, lower(handle)); `); }; exports.down = async function(knex) { await knex.raw(` DROP INDEX actors_socials_actor_id_platform_handle_lower_unique; ALTER TABLE actors_socials ADD CONSTRAINT actors_social_actor_id_platform_handle_unique UNIQUE (actor_id, platform, handle); `); };