From b152f936c1361cc82e21c853335557c3ffa80409 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 6 May 2024 11:05:12 -0400
Subject: [PATCH] Migrate paperclip `_file_size` columns to bigint (#29263)

Co-authored-by: Claire <claire.github-309c@sitedethib.com>
---
 .../instance_media_attachments_measure.rb     |  2 +-
 ...51_convert_file_size_columns_to_big_int.rb | 42 +++++++++++++++++++
 db/schema.rb                                  | 16 +++----
 3 files changed, 51 insertions(+), 9 deletions(-)
 create mode 100644 db/migrate/20240217175251_convert_file_size_columns_to_big_int.rb

diff --git a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb
index 1d2dbbe41..65f444624 100644
--- a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb
+++ b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb
@@ -50,7 +50,7 @@ class Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure < Admin::Metrics:
           WHERE date_trunc('day', media_attachments.created_at)::date = axis.period
             AND #{account_domain_sql(params[:include_subdomains])}
         )
-        SELECT COALESCE(SUM(size), 0) FROM new_media_attachments
+        SELECT COALESCE(SUM(size), 0)::bigint FROM new_media_attachments
       ) AS value
       FROM (
         SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
diff --git a/db/migrate/20240217175251_convert_file_size_columns_to_big_int.rb b/db/migrate/20240217175251_convert_file_size_columns_to_big_int.rb
new file mode 100644
index 000000000..f8223f9c9
--- /dev/null
+++ b/db/migrate/20240217175251_convert_file_size_columns_to_big_int.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require_relative '../../lib/mastodon/migration_helpers'
+
+class ConvertFileSizeColumnsToBigInt < ActiveRecord::Migration[7.1]
+  include Mastodon::MigrationHelpers
+
+  TABLE_COLUMN_MAPPING = [
+    [:accounts, :avatar_file_size],
+    [:accounts, :header_file_size],
+    [:custom_emojis, :image_file_size],
+    [:imports, :data_file_size],
+    [:media_attachments, :file_file_size],
+    [:media_attachments, :thumbnail_file_size],
+    [:preview_cards, :image_file_size],
+    [:site_uploads, :file_file_size],
+  ].freeze
+
+  disable_ddl_transaction!
+
+  def migrate_columns(to_type)
+    TABLE_COLUMN_MAPPING.each do |column_parts|
+      table, column = column_parts
+
+      # Skip this if we're resuming and already did this one.
+      next if column_for(table, column).sql_type == to_type.to_s
+
+      safety_assured do
+        change_column_type_concurrently table, column, to_type
+        cleanup_concurrent_column_type_change table, column
+      end
+    end
+  end
+
+  def up
+    migrate_columns(:bigint)
+  end
+
+  def down
+    migrate_columns(:integer)
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 11f1a202f..ee41a0c3a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -166,11 +166,11 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.string "url"
     t.string "avatar_file_name"
     t.string "avatar_content_type"
-    t.integer "avatar_file_size"
+    t.bigint "avatar_file_size"
     t.datetime "avatar_updated_at", precision: nil
     t.string "header_file_name"
     t.string "header_content_type"
-    t.integer "header_file_size"
+    t.bigint "header_file_size"
     t.datetime "header_updated_at", precision: nil
     t.string "avatar_remote_url"
     t.boolean "locked", default: false, null: false
@@ -368,7 +368,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.string "domain"
     t.string "image_file_name"
     t.string "image_content_type"
-    t.integer "image_file_size"
+    t.bigint "image_file_size"
     t.datetime "image_updated_at", precision: nil
     t.datetime "created_at", precision: nil, null: false
     t.datetime "updated_at", precision: nil, null: false
@@ -558,7 +558,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.datetime "updated_at", precision: nil, null: false
     t.string "data_file_name"
     t.string "data_content_type"
-    t.integer "data_file_size"
+    t.bigint "data_file_size"
     t.datetime "data_updated_at", precision: nil
     t.bigint "account_id", null: false
     t.boolean "overwrite", default: false, null: false
@@ -635,7 +635,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.bigint "status_id"
     t.string "file_file_name"
     t.string "file_content_type"
-    t.integer "file_file_size"
+    t.bigint "file_file_size"
     t.datetime "file_updated_at", precision: nil
     t.string "remote_url", default: "", null: false
     t.datetime "created_at", precision: nil, null: false
@@ -651,7 +651,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.integer "file_storage_schema_version"
     t.string "thumbnail_file_name"
     t.string "thumbnail_content_type"
-    t.integer "thumbnail_file_size"
+    t.bigint "thumbnail_file_size"
     t.datetime "thumbnail_updated_at", precision: nil
     t.string "thumbnail_remote_url"
     t.index ["account_id", "status_id"], name: "index_media_attachments_on_account_id_and_status_id", order: { status_id: :desc }
@@ -855,7 +855,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.string "description", default: "", null: false
     t.string "image_file_name"
     t.string "image_content_type"
-    t.integer "image_file_size"
+    t.bigint "image_file_size"
     t.datetime "image_updated_at", precision: nil
     t.integer "type", default: 0, null: false
     t.text "html", default: "", null: false
@@ -993,7 +993,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.string "var", default: "", null: false
     t.string "file_file_name"
     t.string "file_content_type"
-    t.integer "file_file_size"
+    t.bigint "file_file_size"
     t.datetime "file_updated_at", precision: nil
     t.json "meta"
     t.datetime "created_at", precision: nil, null: false