Emi Matchu
ec6dca1c16
A few pieces here: 1. Convert all tables to `utf8mb4`+`utf8mb4_unicode_520_ci` strings. 2. Configure that as the server's default. 3. Configure the Rails database connection to use this encoding too. Came together pretty well, whew! This has been a LONG time coming, `latin1` is NOT a good charset for the year 2024!
48 lines
1.2 KiB
Ruby
48 lines
1.2 KiB
Ruby
namespace :db do
|
|
desc "Generate SQL to convert all tables and columns to utf8mb4"
|
|
task :utf8_migration => :environment do
|
|
target_charset = "utf8mb4"
|
|
target_collation = "utf8mb4_unicode_520_ci"
|
|
|
|
db = ApplicationRecord.connection
|
|
|
|
# Don't mess with ActiveRecord's internal tables!
|
|
tables = db.tables.reject { |t| t.start_with? "ar_internal_" }
|
|
|
|
ups = []
|
|
downs = []
|
|
tables.sort.each do |table|
|
|
# If the table's default charset/collation doesn't match our goal, we'll
|
|
# modify it!
|
|
db.table_options(table) => {charset:, collation:}
|
|
if charset != target_charset || collation != target_collation
|
|
ups << "ALTER TABLE #{table} CONVERT TO CHARACTER SET " +
|
|
"#{target_charset} COLLATE #{target_collation}"
|
|
downs << "ALTER TABLE #{table} CONVERT TO CHARACTER SET " +
|
|
"#{charset} COLLATE #{collation}"
|
|
end
|
|
end
|
|
|
|
puts <<~MIGRATION_RB
|
|
reversible do |direction|
|
|
direction.up do
|
|
#{sql_as_ruby(ups).indent(2, "\t")}
|
|
end
|
|
|
|
direction.down do
|
|
#{sql_as_ruby(downs).indent(2, "\t")}
|
|
end
|
|
end
|
|
MIGRATION_RB
|
|
end
|
|
end
|
|
|
|
def sql_as_ruby(statements)
|
|
statements.map do |sql|
|
|
<<~EXECUTE_RB
|
|
execute <<-SQL
|
|
#{sql}
|
|
SQL
|
|
EXECUTE_RB
|
|
end.join("")
|
|
end
|