mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #13040 from kamipo/case_sensitive_comparison
Only use BINARY for mysql case sensitive uniqueness check when column has a case insensitive collation. Conflicts: activerecord/CHANGELOG.md
This commit is contained in:
commit
591b8f395d
6 changed files with 62 additions and 6 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
* Only use BINARY for mysql case sensitive uniqueness check when column has a case insensitive collation.
|
||||||
|
|
||||||
|
*Ryuta Kamizono*
|
||||||
|
|
||||||
* Support for Mysql 5.6 Fractional Seconds.
|
* Support for Mysql 5.6 Fractional Seconds.
|
||||||
|
|
||||||
*arthurnn*, *Tatsuhiko Miyagawa*
|
*arthurnn*, *Tatsuhiko Miyagawa*
|
||||||
|
|
|
@ -340,6 +340,11 @@ module ActiveRecord
|
||||||
node
|
node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def case_sensitive_comparison(table, attribute, column, value)
|
||||||
|
value = case_sensitive_modifier(value) unless value.nil?
|
||||||
|
table[attribute].eq(value)
|
||||||
|
end
|
||||||
|
|
||||||
def case_insensitive_comparison(table, attribute, column, value)
|
def case_insensitive_comparison(table, attribute, column, value)
|
||||||
table[attribute].lower.eq(table.lower(value))
|
table[attribute].lower.eq(table.lower(value))
|
||||||
end
|
end
|
||||||
|
|
|
@ -592,6 +592,14 @@ module ActiveRecord
|
||||||
Arel::Nodes::Bin.new(node)
|
Arel::Nodes::Bin.new(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def case_sensitive_comparison(table, attribute, column, value)
|
||||||
|
if column.case_sensitive?
|
||||||
|
table[attribute].eq(value)
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def case_insensitive_comparison(table, attribute, column, value)
|
def case_insensitive_comparison(table, attribute, column, value)
|
||||||
if column.case_sensitive?
|
if column.case_sensitive?
|
||||||
super
|
super
|
||||||
|
|
|
@ -68,8 +68,7 @@ module ActiveRecord
|
||||||
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
|
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
|
||||||
klass.connection.case_insensitive_comparison(table, attribute, column, value)
|
klass.connection.case_insensitive_comparison(table, attribute, column, value)
|
||||||
else
|
else
|
||||||
value = klass.connection.case_sensitive_modifier(value) unless value.nil?
|
klass.connection.case_sensitive_comparison(table, attribute, column, value)
|
||||||
table[attribute].eq(value)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ require 'models/person'
|
||||||
|
|
||||||
class MysqlCaseSensitivityTest < ActiveRecord::TestCase
|
class MysqlCaseSensitivityTest < ActiveRecord::TestCase
|
||||||
class CollationTest < ActiveRecord::Base
|
class CollationTest < ActiveRecord::Base
|
||||||
validates_uniqueness_of :string_cs_column, :case_sensitive => false
|
|
||||||
validates_uniqueness_of :string_ci_column, :case_sensitive => false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
repair_validations(CollationTest)
|
||||||
|
|
||||||
def test_columns_include_collation_different_from_table
|
def test_columns_include_collation_different_from_table
|
||||||
assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation
|
assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation
|
||||||
assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation
|
assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation
|
||||||
|
@ -18,6 +18,7 @@ class MysqlCaseSensitivityTest < ActiveRecord::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_case_insensitive_comparison_for_ci_column
|
def test_case_insensitive_comparison_for_ci_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => false)
|
||||||
CollationTest.create!(:string_ci_column => 'A')
|
CollationTest.create!(:string_ci_column => 'A')
|
||||||
invalid = CollationTest.new(:string_ci_column => 'a')
|
invalid = CollationTest.new(:string_ci_column => 'a')
|
||||||
queries = assert_sql { invalid.save }
|
queries = assert_sql { invalid.save }
|
||||||
|
@ -26,10 +27,29 @@ class MysqlCaseSensitivityTest < ActiveRecord::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_case_insensitive_comparison_for_cs_column
|
def test_case_insensitive_comparison_for_cs_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => false)
|
||||||
CollationTest.create!(:string_cs_column => 'A')
|
CollationTest.create!(:string_cs_column => 'A')
|
||||||
invalid = CollationTest.new(:string_cs_column => 'a')
|
invalid = CollationTest.new(:string_cs_column => 'a')
|
||||||
queries = assert_sql { invalid.save }
|
queries = assert_sql { invalid.save }
|
||||||
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) }
|
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) }
|
||||||
assert_match(/lower/i, cs_uniqueness_query)
|
assert_match(/lower/i, cs_uniqueness_query)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_case_sensitive_comparison_for_ci_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => true)
|
||||||
|
CollationTest.create!(:string_ci_column => 'A')
|
||||||
|
invalid = CollationTest.new(:string_ci_column => 'A')
|
||||||
|
queries = assert_sql { invalid.save }
|
||||||
|
ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) }
|
||||||
|
assert_match(/binary/i, ci_uniqueness_query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_case_sensitive_comparison_for_cs_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => true)
|
||||||
|
CollationTest.create!(:string_cs_column => 'A')
|
||||||
|
invalid = CollationTest.new(:string_cs_column => 'A')
|
||||||
|
queries = assert_sql { invalid.save }
|
||||||
|
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) }
|
||||||
|
assert_no_match(/binary/i, cs_uniqueness_query)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,10 +3,10 @@ require 'models/person'
|
||||||
|
|
||||||
class Mysql2CaseSensitivityTest < ActiveRecord::TestCase
|
class Mysql2CaseSensitivityTest < ActiveRecord::TestCase
|
||||||
class CollationTest < ActiveRecord::Base
|
class CollationTest < ActiveRecord::Base
|
||||||
validates_uniqueness_of :string_cs_column, :case_sensitive => false
|
|
||||||
validates_uniqueness_of :string_ci_column, :case_sensitive => false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
repair_validations(CollationTest)
|
||||||
|
|
||||||
def test_columns_include_collation_different_from_table
|
def test_columns_include_collation_different_from_table
|
||||||
assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation
|
assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation
|
||||||
assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation
|
assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation
|
||||||
|
@ -18,6 +18,7 @@ class Mysql2CaseSensitivityTest < ActiveRecord::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_case_insensitive_comparison_for_ci_column
|
def test_case_insensitive_comparison_for_ci_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => false)
|
||||||
CollationTest.create!(:string_ci_column => 'A')
|
CollationTest.create!(:string_ci_column => 'A')
|
||||||
invalid = CollationTest.new(:string_ci_column => 'a')
|
invalid = CollationTest.new(:string_ci_column => 'a')
|
||||||
queries = assert_sql { invalid.save }
|
queries = assert_sql { invalid.save }
|
||||||
|
@ -26,10 +27,29 @@ class Mysql2CaseSensitivityTest < ActiveRecord::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_case_insensitive_comparison_for_cs_column
|
def test_case_insensitive_comparison_for_cs_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => false)
|
||||||
CollationTest.create!(:string_cs_column => 'A')
|
CollationTest.create!(:string_cs_column => 'A')
|
||||||
invalid = CollationTest.new(:string_cs_column => 'a')
|
invalid = CollationTest.new(:string_cs_column => 'a')
|
||||||
queries = assert_sql { invalid.save }
|
queries = assert_sql { invalid.save }
|
||||||
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/)}
|
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/)}
|
||||||
assert_match(/lower/i, cs_uniqueness_query)
|
assert_match(/lower/i, cs_uniqueness_query)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_case_sensitive_comparison_for_ci_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => true)
|
||||||
|
CollationTest.create!(:string_ci_column => 'A')
|
||||||
|
invalid = CollationTest.new(:string_ci_column => 'A')
|
||||||
|
queries = assert_sql { invalid.save }
|
||||||
|
ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) }
|
||||||
|
assert_match(/binary/i, ci_uniqueness_query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_case_sensitive_comparison_for_cs_column
|
||||||
|
CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => true)
|
||||||
|
CollationTest.create!(:string_cs_column => 'A')
|
||||||
|
invalid = CollationTest.new(:string_cs_column => 'A')
|
||||||
|
queries = assert_sql { invalid.save }
|
||||||
|
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) }
|
||||||
|
assert_no_match(/binary/i, cs_uniqueness_query)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue