Skip to content

Instantly share code, notes, and snippets.

@amuntasim
Last active June 2, 2022 21:06
Show Gist options
  • Save amuntasim/f3b12f20a30e9a9f3fb0 to your computer and use it in GitHub Desktop.
Save amuntasim/f3b12f20a30e9a9f3fb0 to your computer and use it in GitHub Desktop.

Revisions

  1. amuntasim revised this gist Aug 9, 2015. 1 changed file with 41 additions and 29 deletions.
    70 changes: 41 additions & 29 deletions change_mysql_character_set_and_collation
    Original file line number Diff line number Diff line change
    @@ -1,34 +1,46 @@
    #!/usr/bin/env ruby

    # Put this file in the root of your Rails project,
    # then run it to output the SQL needed to change all
    # your tables and columns to the same character set
    # and collation.
    #
    # > ruby character_set_and_collation.rb
    ##Create a migration
    ### rails g migration make_unicode_friendly

    CHARACTER_SET = 'utf8'
    COLLATION = 'utf8_general_ci'
    class MakeUnicodeFriendly < ActiveRecord::Migration
    def change
    alter_database_and_tables_charsets "utf8", "utf8_general_ci"
    end

    schema = File.open('db/schema.rb', 'r').read
    rows = schema.split("\n")
    private
    def alter_database_and_tables_charsets charset = default_charset, collation = default_collation
    case connection.adapter_name
    when 'Mysql2'
    execute "ALTER DATABASE #{connection.current_database} CHARACTER SET #{charset} COLLATE #{collation}"

    table_name = nil
    rows.each do |row|
    if row =~ /create_table/
    table_name = row.match(/create_table "(\w+)"/)[1]
    puts "ALTER TABLE `#{table_name}` DEFAULT CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    elsif row =~ /t\.string/
    field_name = row.match(/"(\w+)"/)[1]
    limit = row =~ /limit:\s*(\d*)/ ? row.match(/limit:\s*(\d*)/)[1] : 255
    puts "ALTER TABLE `#{table_name}` CHANGE `#{field_name}` `#{field_name}` VARCHAR(#{limit}) CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    elsif row =~ /t\.text/
    field_name = row.match(/"(\w+)"/)[1]
    if row =~ /limit:\s*(\d*)/
    limit = row.match(/limit:\s*(\d*)/)[1]
    puts "ALTER TABLE `#{table_name}` CHANGE `#{field_name}` `#{field_name}` TEXT(#{limit}) CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    else
    puts "ALTER TABLE `#{table_name}` CHANGE `#{field_name}` `#{field_name}` TEXT CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    connection.tables.each do |table|
    execute "ALTER TABLE #{table} CONVERT TO CHARACTER SET #{charset} COLLATE #{collation}"
    end
    else
    # OK, not quite irreversible but can't be done if there's not
    # the code here to support it...
    raise ActiveRecord::IrreversibleMigration.new("Migration error: Unsupported database for migration to UTF-8 support")
    end
    end
    end

    def default_charset
    case connection.adapter_name
    when 'Mysql2'
    execute("show variables like 'character_set_server'").fetch_hash['Value']
    else
    nil
    end
    end

    def default_collation
    case connection.adapter_name
    when 'Mysql2'
    execute("show variables like 'collation_server'").fetch_hash['Value']
    else
    nil
    end
    end

    def connection
    ActiveRecord::Base.connection
    end
    end
  2. amuntasim renamed this gist Feb 12, 2015. 1 changed file with 0 additions and 0 deletions.
  3. amuntasim created this gist Feb 12, 2015.
    34 changes: 34 additions & 0 deletions change mysql table character set and collation
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    #!/usr/bin/env ruby

    # Put this file in the root of your Rails project,
    # then run it to output the SQL needed to change all
    # your tables and columns to the same character set
    # and collation.
    #
    # > ruby character_set_and_collation.rb

    CHARACTER_SET = 'utf8'
    COLLATION = 'utf8_general_ci'

    schema = File.open('db/schema.rb', 'r').read
    rows = schema.split("\n")

    table_name = nil
    rows.each do |row|
    if row =~ /create_table/
    table_name = row.match(/create_table "(\w+)"/)[1]
    puts "ALTER TABLE `#{table_name}` DEFAULT CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    elsif row =~ /t\.string/
    field_name = row.match(/"(\w+)"/)[1]
    limit = row =~ /limit:\s*(\d*)/ ? row.match(/limit:\s*(\d*)/)[1] : 255
    puts "ALTER TABLE `#{table_name}` CHANGE `#{field_name}` `#{field_name}` VARCHAR(#{limit}) CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    elsif row =~ /t\.text/
    field_name = row.match(/"(\w+)"/)[1]
    if row =~ /limit:\s*(\d*)/
    limit = row.match(/limit:\s*(\d*)/)[1]
    puts "ALTER TABLE `#{table_name}` CHANGE `#{field_name}` `#{field_name}` TEXT(#{limit}) CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    else
    puts "ALTER TABLE `#{table_name}` CHANGE `#{field_name}` `#{field_name}` TEXT CHARACTER SET #{CHARACTER_SET} COLLATE #{COLLATION};"
    end
    end
    end