-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
179 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
ActiveSupport.on_load :active_record do | ||
require 'ar_mysql_column_charset' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
class SetCharsetForMysql < ActiveRecord::Migration | ||
def all_models | ||
@all_models ||= [ | ||
Agent, | ||
AgentLog, | ||
Contact, | ||
Event, | ||
Link, | ||
Scenario, | ||
ScenarioMembership, | ||
User, | ||
UserCredential, | ||
] | ||
end | ||
|
||
def change | ||
conn = ActiveRecord::Base.connection | ||
|
||
# This is migration is for MySQL only. | ||
return unless conn.is_a?(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter) | ||
|
||
reversible do |dir| | ||
dir.up do | ||
all_models.each { |model| | ||
table_name = model.table_name | ||
|
||
# `contacts` may not exist | ||
next unless connection.table_exists? table_name | ||
|
||
model.columns.each { |column| | ||
name = column.name | ||
type = column.type | ||
limit = column.limit | ||
options = { | ||
limit: limit, | ||
null: column.null, | ||
default: column.default, | ||
} | ||
|
||
case type | ||
when :string, :text | ||
case name | ||
when 'username' | ||
options.update(limit: 767 / 4, charset: 'utf8mb4', collation: 'utf8mb4_bin') | ||
when 'message', 'options', 'name', 'memory', | ||
'handler', 'last_error', 'payload', 'description' | ||
options.update(charset: 'utf8mb4', collation: 'utf8mb4_bin') | ||
# Below is a bit of paranoia | ||
when 'guid' | ||
options.update(charset: 'ascii', collation: 'ascii_bin') | ||
when 'email' | ||
options.update(collation: 'utf8_bin') | ||
else | ||
next | ||
end | ||
else | ||
next | ||
end | ||
|
||
change_column table_name, name, type, options | ||
} | ||
|
||
execute 'ALTER TABLE %s CHARACTER SET utf8 COLLATE utf8_general_ci' % table_name | ||
} | ||
|
||
execute 'ALTER DATABASE %s CHARACTER SET utf8 COLLATE utf8_general_ci' % conn.current_database | ||
end | ||
|
||
dir.down do | ||
# Do nada; no use to go back | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
require 'active_record' | ||
|
||
module ActiveRecord::ConnectionAdapters | ||
class ColumnDefinition | ||
module CharsetSupport | ||
attr_accessor :charset, :collation | ||
end | ||
|
||
prepend CharsetSupport | ||
end | ||
|
||
class TableDefinition | ||
module CharsetSupport | ||
def new_column_definition(name, type, options) | ||
column = super | ||
column.charset = options[:charset] | ||
column.collation = options[:collation] | ||
column | ||
end | ||
end | ||
|
||
prepend CharsetSupport | ||
end | ||
|
||
class AbstractMysqlAdapter | ||
module CharsetSupport | ||
def prepare_column_options(column, types) | ||
spec = super | ||
conn = ActiveRecord::Base.connection | ||
spec[:charset] = column.charset.inspect if column.charset && column.charset != conn.charset | ||
spec[:collation] = column.collation.inspect if column.collation && column.collation != conn.collation | ||
spec | ||
end | ||
|
||
def migration_keys | ||
super + [:charset, :collation] | ||
end | ||
end | ||
|
||
prepend CharsetSupport | ||
|
||
class SchemaCreation | ||
module CharsetSupport | ||
def column_options(o) | ||
column_options = super | ||
column_options[:charset] = o.charset unless o.charset.nil? | ||
column_options[:collation] = o.collation unless o.collation.nil? | ||
column_options | ||
end | ||
|
||
def add_column_options!(sql, options) | ||
if options[:charset] | ||
sql << " CHARACTER SET #{options[:charset]}" | ||
end | ||
|
||
if options[:collation] | ||
sql << " COLLATE #{options[:collation]}" | ||
end | ||
|
||
super | ||
end | ||
end | ||
|
||
prepend CharsetSupport | ||
end | ||
|
||
class Column | ||
module CharsetSupport | ||
attr_reader :charset | ||
|
||
def initialize(*args) | ||
super | ||
@charset = @collation[/\A[^_]+/] unless @collation.nil? | ||
end | ||
end | ||
|
||
prepend CharsetSupport | ||
end | ||
end | ||
end if Module.method_defined?(:prepend) # ruby >=2.0 |