From 6cb176cddfc1541da20da4e75b472c3405f6c933 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 4 Oct 2017 21:24:08 +0900 Subject: Extract `default_uniqueness_comparison` to ease to handle mismatched collation issues In MySQL, the default collation is case insensitive. Since the uniqueness validator enforces case sensitive comparison by default, it frequently causes mismatched collation issues (performance, weird behavior, etc) to MySQL users. https://grosser.it/2009/12/11/validates_uniqness_of-mysql-slow/ https://github.com/rails/rails/issues/1399 https://github.com/rails/rails/pull/13465 https://github.com/gitlabhq/gitlabhq/commit/c1dddf8c7d947691729f6d64a8ea768b5c915855 https://github.com/huginn/huginn/pull/1330#discussion_r55152573 This extracts `default_uniqueness_comparison` to ease to handle the mismatched collation issues on the connection. --- .../lib/active_record/connection_adapters/abstract_adapter.rb | 4 ++++ activerecord/lib/active_record/validations/uniqueness.rb | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 3c9510e469..c1d846f58d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -506,6 +506,10 @@ module ActiveRecord @connection end + def default_uniqueness_comparison(attribute, value) # :nodoc: + case_sensitive_comparison(attribute, value) + end + def case_sensitive_comparison(attribute, value) # :nodoc: attribute.eq(value) end diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index fb745af125..88ae62c681 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -12,7 +12,7 @@ module ActiveRecord raise ArgumentError, "#{options[:scope]} is not supported format for :scope option. " \ "Pass a symbol or an array of symbols instead: `scope: :user_id`" end - super({ case_sensitive: true }.merge!(options)) + super @klass = options[:class] end @@ -62,6 +62,8 @@ module ActiveRecord if bind.nil? attr.eq(bind) + elsif !options.key?(:case_sensitive) + klass.connection.default_uniqueness_comparison(attr, bind) elsif options[:case_sensitive] klass.connection.case_sensitive_comparison(attr, bind) else -- cgit v1.2.3