Sequel.migration do up do # 1. Create benchmark_profiles create_table(:benchmark_profiles) do primary_key :id String :label, null: false String :settings, null: false foreign_key :benchmark_id, :benchmarks, null: false, on_delete: :cascade DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP end # 2. Create join table (tests <-> benchmark_profiles) create_table(:benchmark_profiles_tests) do primary_key :id foreign_key :test_id, :tests, null: false, on_delete: :cascade foreign_key :benchmark_profile_id, :benchmark_profiles, null: false, on_delete: :cascade index [:test_id, :benchmark_profile_id], unique: true end # 3. Add benchmark_profile_id to results alter_table(:results) do add_foreign_key :benchmark_profile_id, :benchmark_profiles, null: true, on_delete: :cascade end # 4. Migrate data from old schema from(:benchmarks).each do |b_row| # Create a BenchmarkProfile for this (test, benchmark) pair bp_id = self[:benchmark_profiles].insert( benchmark_id: b_row[:id], label: 'Default', settings: '{}' ) from(:benchmarks_tests).each do |bt_row| if bt_row[:benchmark_id] == b_row[:id] # Link it to the test self[:benchmark_profiles_tests].insert( test_id: bt_row[:test_id], benchmark_profile_id: bp_id ) # Update results belonging to this test + benchmark pair self[:results] .where(test_id: bt_row[:test_id], benchmark_id: bt_row[:benchmark_id]) .update(benchmark_profile_id: bp_id) end end end # 5. Clean up old schema alter_table(:results) do drop_foreign_key :benchmark_id end drop_table(:benchmarks_tests) end down do # 1. Recreate old join table create_table(:benchmarks_tests) do foreign_key :test_id, :tests, null: false foreign_key :benchmark_id, :benchmarks, null: false end # 2. Add benchmark_id back to results alter_table(:results) do add_foreign_key :benchmark_id, :benchmarks, null: true end # 3. Restore data from(:benchmark_profiles_tests).each do |bpt_row| bp = self[:benchmark_profiles][id: bpt_row[:benchmark_profile_id]] next unless bp # safety check # Recreate old benchmarks_tests entry self[:benchmarks_tests].insert( test_id: bpt_row[:test_id], benchmark_id: bp[:benchmark_id] ) # Update results to point back to benchmark_id self[:results] .where(test_id: bpt_row[:test_id], benchmark_profile_id: bp[:id]) .update(benchmark_id: bp[:benchmark_id]) end # 4. Remove new schema alter_table(:results) do drop_foreign_key :benchmark_profile_id end drop_table(:benchmark_profiles_tests) drop_table(:benchmark_profiles) end end