From 6b3d85e00c0246d3a49bd222b1132ddc661b13c9 Mon Sep 17 00:00:00 2001 From: hiromi-ogawa Date: Tue, 16 Apr 2024 15:03:37 +0900 Subject: [PATCH] Fix column collations and table default collation in a migration --- CHANGELOG.md | 1 + db/migrate/20240415080757_fix_collations.rb | 34 +++++++++++++++++++++ spec/dummy/db/schema.rb | 32 +++++++++---------- 3 files changed, 51 insertions(+), 16 deletions(-) create mode 100644 db/migrate/20240415080757_fix_collations.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 0052dae..ca543b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Support Ruby 3.0 - Drop support for Ruby < 3.0 - Drop support for MySQL 5.7 + - A new migration is added to fix collations properly in MySQL 8.0 ## v2.8.0 (2021-12-23) ### New features diff --git a/db/migrate/20240415080757_fix_collations.rb b/db/migrate/20240415080757_fix_collations.rb new file mode 100644 index 0000000..3eeb569 --- /dev/null +++ b/db/migrate/20240415080757_fix_collations.rb @@ -0,0 +1,34 @@ +# In MySQL 8.0, the default collation for utf8mb4 is changed to utf8mb4_0900_ai_ci. +# The column collations are utf8mb4_0900_ai_ci after we ran migrations prior to this +# on MySQL 8.0 because we did not specify collation in create_table (thus the default is used). +# This happens on testing/development but we want to keep utf8mb4_general_ci. +# +# Note that running this should not affect the actual schema and data +# unless you've ran prior migrations on MySQL 8.0. +class FixCollations < ActiveRecord::Migration[6.1] + def change + reversible do |direction| + direction.up do + # alter column collations and default collation of every tables defined to utf8mb4_general_ci + execute 'ALTER TABLE barbeque_apps CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_docker_containers CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_ecs_hako_tasks CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_job_executions CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_job_queues CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_job_retries CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_retry_configs CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_slack_notifications CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + execute 'ALTER TABLE barbeque_sns_subscriptions CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + + # barbeque_job_definitions contains a column with explicitly specified collation + execute 'ALTER TABLE barbeque_job_definitions DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci' + change_column :barbeque_job_definitions, :command, :string, collation: 'utf8mb4_general_ci' + change_column :barbeque_job_definitions, :description, :text, collation: 'utf8mb4_general_ci' + end + + direction.down do + raise ActiveRecord::IrreversibleMigration + end + end + end +end diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb index 212df31..5578cac 100644 --- a/spec/dummy/db/schema.rb +++ b/spec/dummy/db/schema.rb @@ -2,17 +2,17 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_10_29_105530) do +ActiveRecord::Schema.define(version: 2024_04_15_080757) do - create_table "barbeque_apps", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_apps", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.string "name", null: false t.string "docker_image", null: false t.text "description" @@ -21,7 +21,7 @@ t.index ["name"], name: "index_barbeque_apps_on_name", unique: true end - create_table "barbeque_docker_containers", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_docker_containers", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.string "message_id", null: false t.string "container_id", null: false t.datetime "created_at", null: false @@ -29,7 +29,7 @@ t.index ["message_id"], name: "index_barbeque_docker_containers_on_message_id", unique: true end - create_table "barbeque_ecs_hako_tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_ecs_hako_tasks", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.string "message_id", null: false t.string "cluster", null: false t.string "task_arn", null: false @@ -38,7 +38,7 @@ t.index ["message_id"], name: "index_barbeque_ecs_hako_tasks_on_message_id", unique: true end - create_table "barbeque_job_definitions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_job_definitions", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.string "job", null: false, collation: "utf8mb4_bin" t.integer "app_id", null: false t.string "command", null: false @@ -48,7 +48,7 @@ t.index ["job", "app_id"], name: "index_barbeque_job_definitions_on_job_and_app_id", unique: true end - create_table "barbeque_job_executions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_job_executions", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.string "message_id", null: false t.integer "status", default: 0, null: false t.datetime "created_at", null: false @@ -62,7 +62,7 @@ t.index ["status"], name: "index_barbeque_job_executions_on_status" end - create_table "barbeque_job_queues", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_job_queues", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.string "name", null: false t.text "description" t.string "queue_url", null: false @@ -71,7 +71,7 @@ t.index ["name"], name: "index_barbeque_job_queues_on_name", unique: true end - create_table "barbeque_job_retries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_job_retries", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.string "message_id", null: false t.integer "job_execution_id", null: false t.integer "status", default: 0, null: false @@ -82,7 +82,7 @@ t.index ["status"], name: "index_barbeque_job_retries_on_status" end - create_table "barbeque_retry_configs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_retry_configs", charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.integer "job_definition_id", null: false t.integer "retry_limit", default: 3, null: false t.float "base_delay", default: 15.0, null: false @@ -93,7 +93,7 @@ t.index ["job_definition_id"], name: "index_barbeque_retry_configs_on_job_definition_id", unique: true end - create_table "barbeque_slack_notifications", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t| + create_table "barbeque_slack_notifications", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| t.integer "job_definition_id" t.string "channel", null: false t.boolean "notify_success", default: false, null: false @@ -103,7 +103,7 @@ t.boolean "notify_failure_only_if_retry_limit_reached", default: false, null: false end - create_table "barbeque_sns_subscriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "barbeque_sns_subscriptions", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| t.string "topic_arn", null: false t.integer "job_queue_id", null: false t.integer "job_definition_id", null: false