require "rubygems" require "sequel" DB = Sequel.mysql('test', :host => 'localhost') DB << " create table if not exists items( id int primary key, component_id int ) " DB << " create table if not exists links( first int references items (id), second int references items (id), key (first), key (second), unique key (first, second) ) " DB << " create table if not exists components_to_merge( component1 int, component2 int, key(component1) ) " # Set up random test data DB[:items].delete DB[:links].delete DB[:items].insert_multiple((0..1000).map{|i| {:id => i}}) DB[:links].insert_multiple( (0..800).map{|i| [rand(1000), rand(1000)]}.uniq.map{|x, y| {:first => x, :second => y}} ) def merge_components_step DB[:components_to_merge].delete DB << " insert into components_to_merge select distinct t1.component_id c1, t2.component_id c2 from links join items t1 on links.first = t1.id join items t2 on links.second = t2.id where t1.component_id != t2.component_id " # Ensure symmetricity DB << "insert into components_to_merge select component2, component1 from components_to_merge" DB << " update items join ( select component1 source, min(component2) target from components_to_merge group by source ) new_components on new_components.source = component_id set items.component_id = least(items.component_id, target) " DB[:components_to_merge].count() end DB[:items].update(:component_id => :id) while merge_components_step > 0 end