提交 84efde74 编写于 作者: S Sean Griffin

Revert "Extract `PredicateBuilder::CaseSensitiveHandler`"

This reverts commit 3a1f6fe7.

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.
上级 7ba3a48d
......@@ -433,16 +433,16 @@ def raw_connection
@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)
......
......@@ -613,11 +613,12 @@ def primary_keys(table_name) # :nodoc:
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)
......
......@@ -4,7 +4,6 @@ class PredicateBuilder # :nodoc:
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 @@ def initialize(table)
@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 @@ def build_from_hash(attributes)
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 @@ def expand_from_hash(attributes)
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 @@ def create_binds_for_hash(attributes, options)
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 @@ def can_be_bound?(column_name, value)
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
......
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
......@@ -17,7 +17,7 @@ def build(opts, other)
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
......
......@@ -50,7 +50,37 @@ def find_finder_class_for(record) #:nodoc:
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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册