Skip to content

Commit

Permalink
sets limit 191 for schema_migrations#version in mysql2 if the encodin…
Browse files Browse the repository at this point in the history
…g is "utf8mb4"

Please, see rationale in the included CHANGELOG patch.
  • Loading branch information
fxn committed Mar 17, 2013
1 parent b365354 commit 8744632
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 5 deletions.
15 changes: 15 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
## Rails 4.0.0 (unreleased) ##

* The length of the `version` column in the `schema_migrations` table
created by the `mysql2` adapter is 191 if the encoding is "utf8mb4".

The "utf8" encoding in MySQL has support for a maximum of 3 bytes per character,
and only contains characters from the BMP. The recently added
[utf8mb4](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)
encoding extends the support to four bytes. As of this writing, said encoding
is supported in the betas of the `mysql2` gem.

Setting the encoding to "utf8mb4" has
[a few implications](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-upgrading.html).
This change addresses the max length for indexes, which is 191 instead of 255.

*Xavier Noria*

* Counter caches on associations will now stay valid when attributes are
updated (not just when records are created or destroyed), for example,
when calling `update_attributes`. The following code now works:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ def initialize(connection, logger, connection_options, config)
configure_connection
end

MAX_INDEX_LENGTH_FOR_UTF8MB4 = 191
def initialize_schema_migrations_table
if @config[:encoding] == 'utf8mb4'
ActiveRecord::SchemaMigration.create_table(MAX_INDEX_LENGTH_FOR_UTF8MB4)
else
ActiveRecord::SchemaMigration.create_table
end
end

def supports_explain?
true
end
Expand Down
13 changes: 8 additions & 5 deletions activerecord/lib/active_record/schema_migration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ def self.index_name
"#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
end

def self.create_table
def self.create_table(limit=nil)
unless connection.table_exists?(table_name)
connection.create_table(table_name, :id => false) do |t|
t.column :version, :string, :null => false
version_options = {null: false}
version_options[:limit] = limit if limit

connection.create_table(table_name, id: false) do |t|
t.column :version, :string, version_options
end
connection.add_index table_name, :version, :unique => true, :name => index_name
connection.add_index table_name, :version, unique: true, name: index_name
end
end

def self.drop_table
if connection.table_exists?(table_name)
connection.remove_index table_name, :name => index_name
connection.remove_index table_name, name: index_name
connection.drop_table(table_name)
end
end
Expand Down
26 changes: 26 additions & 0 deletions activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require "cases/helper"

module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter
class SchemaMigrationsTest < ActiveRecord::TestCase
def test_initializes_schema_migrations_for_encoding_utf8mb4
conn = ActiveRecord::Base.connection

smtn = ActiveRecord::Migrator.schema_migrations_table_name
conn.drop_table(smtn) if conn.table_exists?(smtn)

config = conn.instance_variable_get(:@config)
original_encoding = config[:encoding]

config[:encoding] = 'utf8mb4'
conn.initialize_schema_migrations_table

assert conn.column_exists?(smtn, :version, :string, limit: Mysql2Adapter::MAX_INDEX_LENGTH_FOR_UTF8MB4)
ensure
config[:encoding] = original_encoding
end
end
end
end
end

0 comments on commit 8744632

Please sign in to comment.