diff options
author | Sean Griffin <sean@seantheprogrammer.com> | 2016-08-31 12:38:37 -0400 |
---|---|---|
committer | Sean Griffin <sean@seantheprogrammer.com> | 2016-08-31 12:38:37 -0400 |
commit | 84efde740dc357de3ace08b2f2fd7a4a67dbd9bd (patch) | |
tree | c858f06849f59885cb736027d49f954de2ca59b4 /activerecord | |
parent | 7ba3a48df5bfdc5e98506bb829f937e03b55a5b3 (diff) | |
download | rails-84efde740dc357de3ace08b2f2fd7a4a67dbd9bd.tar.gz rails-84efde740dc357de3ace08b2f2fd7a4a67dbd9bd.tar.bz2 rails-84efde740dc357de3ace08b2f2fd7a4a67dbd9bd.zip |
Revert "Extract `PredicateBuilder::CaseSensitiveHandler`"
This reverts commit 3a1f6fe7b4a70bf0698b0684dd48ac712c6883b6.
This commit takes the code in a direction that I am looking to avoid.
The predicate builder should be purely concerned with AST construction
as it matters to methods like `where`. Things like case sensitivity
should continue to be handled elsewhere.
Diffstat (limited to 'activerecord')
6 files changed, 51 insertions, 51 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 4dde525ebc..0c7197a002 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -433,16 +433,16 @@ module ActiveRecord @connection end - def case_sensitive_comparison(attribute, column, value) # :nodoc: - attribute.eq(value) + def case_sensitive_comparison(table, attribute, column, value) + table[attribute].eq(Arel::Nodes::BindParam.new) end - def case_insensitive_comparison(attribute, column, value) # :nodoc: + def case_insensitive_comparison(table, attribute, column, value) if can_perform_case_insensitive_comparison_for?(column) - value = attribute.relation.lower(value) - attribute = attribute.lower + table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new)) + else + table[attribute].eq(Arel::Nodes::BindParam.new) end - attribute.eq(value) end def can_perform_case_insensitive_comparison_for?(column) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 3a28879c15..4333cd1f57 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -613,11 +613,12 @@ module ActiveRecord SQL end - def case_sensitive_comparison(attribute, column, value) # :nodoc: + def case_sensitive_comparison(table, attribute, column, value) if column.collation && !column.case_sensitive? - value = Arel::Nodes::Bin.new(value) + table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new)) + else + super end - attribute.eq(value) end def can_perform_case_insensitive_comparison_for?(column) diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 29422bf131..780a1ee422 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -4,7 +4,6 @@ module ActiveRecord require "active_record/relation/predicate_builder/association_query_handler" require "active_record/relation/predicate_builder/base_handler" require "active_record/relation/predicate_builder/basic_object_handler" - require "active_record/relation/predicate_builder/case_sensitive_handler" require "active_record/relation/predicate_builder/class_handler" require "active_record/relation/predicate_builder/polymorphic_array_handler" require "active_record/relation/predicate_builder/range_handler" @@ -17,7 +16,6 @@ module ActiveRecord @handlers = [] register_handler(BasicObject, BasicObjectHandler.new) - register_handler(CaseSensitiveHandler::Value, CaseSensitiveHandler.new) register_handler(Class, ClassHandler.new(self)) register_handler(Base, BaseHandler.new(self)) register_handler(Range, RangeHandler.new) @@ -33,9 +31,9 @@ module ActiveRecord expand_from_hash(attributes) end - def create_binds(attributes, options) + def create_binds(attributes) attributes = convert_dot_notation_to_hash(attributes) - create_binds_for_hash(attributes, options) + create_binds_for_hash(attributes) end def self.references(attributes) @@ -84,14 +82,14 @@ module ActiveRecord end end - def create_binds_for_hash(attributes, options) + def create_binds_for_hash(attributes) result = attributes.dup binds = [] attributes.each do |column_name, value| case when value.is_a?(Hash) && !table.has_column?(column_name) - attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value, options) + attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value) result[column_name] = attrs binds += bvs next @@ -110,15 +108,11 @@ module ActiveRecord end result[column_name] = RangeHandler::RangeWithBinds.new(first, last, value.exclude_end?) - when can_be_bound?(column_name, value) - result[column_name] = - if perform_case_sensitive?(options) - CaseSensitiveHandler::Value.new( - Arel::Nodes::BindParam.new, table, options[:case_sensitive]) - else - Arel::Nodes::BindParam.new - end - binds << build_bind_param(column_name, value) + else + if can_be_bound?(column_name, value) + result[column_name] = Arel::Nodes::BindParam.new + binds << build_bind_param(column_name, value) + end end # Find the foreign key when using queries such as: @@ -170,10 +164,6 @@ module ActiveRecord end end - def perform_case_sensitive?(options) - options.key?(:case_sensitive) - end - def build_bind_param(column_name, value) Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name)) end diff --git a/activerecord/lib/active_record/relation/predicate_builder/case_sensitive_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/case_sensitive_handler.rb deleted file mode 100644 index acf0bbd829..0000000000 --- a/activerecord/lib/active_record/relation/predicate_builder/case_sensitive_handler.rb +++ /dev/null @@ -1,21 +0,0 @@ -module ActiveRecord - class PredicateBuilder - class CaseSensitiveHandler # :nodoc: - def call(attribute, value) - value.call(attribute) - end - - class Value < Struct.new(:value, :table, :case_sensitive?) # :nodoc: - def call(attribute) - klass = table.send(:klass) - column = klass.column_for_attribute(attribute.name) - if case_sensitive? - klass.connection.case_sensitive_comparison(attribute, column, value) - else - klass.connection.case_insensitive_comparison(attribute, column, value) - end - end - end - end - end -end diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb index 122ab04c00..dc00149130 100644 --- a/activerecord/lib/active_record/relation/where_clause_factory.rb +++ b/activerecord/lib/active_record/relation/where_clause_factory.rb @@ -17,7 +17,7 @@ module ActiveRecord attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes) attributes.stringify_keys! - attributes, binds = predicate_builder.create_binds(attributes, other.last || {}) + attributes, binds = predicate_builder.create_binds(attributes) parts = predicate_builder.build_from_hash(attributes) when Arel::Nodes::Node diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 08c4b01439..8c4930a81d 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -50,7 +50,37 @@ module ActiveRecord end def build_relation(klass, attribute, value) # :nodoc: - klass.unscoped.where!({ attribute => value }, options) + if reflection = klass._reflect_on_association(attribute) + attribute = reflection.foreign_key + value = value.attributes[reflection.klass.primary_key] unless value.nil? + end + + if value.nil? + return klass.unscoped.where!(attribute => value) + end + + # the attribute may be an aliased attribute + if klass.attribute_alias?(attribute) + attribute = klass.attribute_alias(attribute) + end + + attribute_name = attribute.to_s + + table = klass.arel_table + column = klass.columns_hash[attribute_name] + cast_type = klass.type_for_attribute(attribute_name) + + comparison = if !options[:case_sensitive] + # will use SQL LOWER function before comparison, unless it detects a case insensitive collation + klass.connection.case_insensitive_comparison(table, attribute, column, value) + else + klass.connection.case_sensitive_comparison(table, attribute, column, value) + end + klass.unscoped.tap do |scope| + parts = [comparison] + binds = [Relation::QueryAttribute.new(attribute_name, value, cast_type)] + scope.where_clause += Relation::WhereClause.new(parts, binds) + end end def scope_relation(record, relation) |