diff --git a/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb b/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb new file mode 100644 index 0000000000000000000000000000000000000000..4f5750a3e2dd49390013307fbad2fef942993359 --- /dev/null +++ b/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb @@ -0,0 +1,66 @@ +class CleanupDuplicatesAndAddUniqueIndexes < ActiveRecord::Migration + class Post < ActiveRecord::Base + end + + class StatusMessage < Post + end + + class Photo < ActiveRecord::Base + belongs_to :status_message, foreign_key: :status_message_guid, primary_key: :guid + end + + class ShareVisibility < ActiveRecord::Base + end + + def up + # temporary index to speed up the migration + add_index :photos, :guid, length: 191 + + # fix share visibilities for private photos + if AppConfig.postgres? + execute "UPDATE share_visibilities" \ + " SET shareable_id = (SELECT MIN(p3.id) FROM photos as p3 WHERE p3.guid = p1.guid)" \ + " FROM photos as p1, photos as p2" \ + " WHERE p1.id = share_visibilities.shareable_id AND (p1.guid = p2.guid AND p1.id > p2.id)" \ + " AND share_visibilities.shareable_type = 'Photo'" + else + execute "UPDATE share_visibilities" \ + " INNER JOIN photos as p1 ON p1.id = share_visibilities.shareable_id" \ + " INNER JOIN photos as p2 ON p1.guid = p2.guid AND p1.id > p2.id" \ + " SET share_visibilities.shareable_id = (SELECT MIN(p3.id) FROM photos as p3 WHERE p3.guid = p1.guid)" \ + " WHERE share_visibilities.shareable_type = 'Photo'" + end + + %i(conversations messages photos polls poll_answers poll_participations).each do |table| + delete_duplicates_and_create_unique_index(table) + end + + # fix photo public flag again ... + Photo.joins(:status_message).where(posts: {public: true}).update_all(public: true) + + ShareVisibility.joins("INNER JOIN photos ON photos.id = share_visibilities.shareable_id") + .where(shareable_type: "Photo", photos: {public: true}).delete_all + end + + def down + raise ActiveRecord::IrreversibleMigration + end + + private + + def delete_duplicates_and_create_unique_index(table) + # temporary index to speed up the migration + add_index table, :guid, length: 191 unless table == :photos + + if AppConfig.postgres? + execute "DELETE FROM #{table} AS t1 USING #{table} AS t2 WHERE t1.guid = t2.guid AND t1.id > t2.id" + else + execute "DELETE t1 FROM #{table} t1, #{table} t2 WHERE t1.guid = t2.guid AND t1.id > t2.id" + end + + remove_index table, column: :guid + + # now create unique index \o/ + add_index table, :guid, length: 191, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 382d7ef2bb82d14b0d22de374098e5e73b06c783..41c0ddf5c50c472c7450f4aa7ed277334f751bb5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -149,6 +149,7 @@ ActiveRecord::Schema.define(version: 20160531170531) do end add_index "conversations", ["author_id"], name: "conversations_author_id_fk", using: :btree + add_index "conversations", ["guid"], name: "index_conversations_on_guid", unique: true, length: {"guid"=>191}, using: :btree create_table "id_tokens", force: :cascade do |t| t.integer "authorization_id", limit: 4 @@ -231,6 +232,7 @@ ActiveRecord::Schema.define(version: 20160531170531) do add_index "messages", ["author_id"], name: "index_messages_on_author_id", using: :btree add_index "messages", ["conversation_id"], name: "messages_conversation_id_fk", using: :btree + add_index "messages", ["guid"], name: "index_messages_on_guid", unique: true, length: {"guid"=>191}, using: :btree create_table "notification_actors", force: :cascade do |t| t.integer "notification_id", limit: 4 @@ -360,6 +362,7 @@ ActiveRecord::Schema.define(version: 20160531170531) do t.integer "width", limit: 4 end + add_index "photos", ["guid"], name: "index_photos_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "photos", ["status_message_guid"], name: "index_photos_on_status_message_guid", length: {"status_message_guid"=>191}, using: :btree create_table "pods", force: :cascade do |t| @@ -389,6 +392,7 @@ ActiveRecord::Schema.define(version: 20160531170531) do t.integer "vote_count", limit: 4, default: 0 end + add_index "poll_answers", ["guid"], name: "index_poll_answers_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "poll_answers", ["poll_id"], name: "index_poll_answers_on_poll_id", using: :btree create_table "poll_participations", force: :cascade do |t| @@ -401,6 +405,7 @@ ActiveRecord::Schema.define(version: 20160531170531) do t.datetime "updated_at" end + add_index "poll_participations", ["guid"], name: "index_poll_participations_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "poll_participations", ["poll_id"], name: "index_poll_participations_on_poll_id", using: :btree create_table "polls", force: :cascade do |t| @@ -412,6 +417,7 @@ ActiveRecord::Schema.define(version: 20160531170531) do t.datetime "updated_at" end + add_index "polls", ["guid"], name: "index_polls_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "polls", ["status_message_id"], name: "index_polls_on_status_message_id", using: :btree create_table "posts", force: :cascade do |t|