mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Refactor build_relation
in the uniqueness validator to avoid low level predicate construction
This commit is contained in:
parent
235eb91bad
commit
eb5fef554f
3 changed files with 29 additions and 27 deletions
|
@ -504,15 +504,17 @@ module ActiveRecord
|
|||
@connection
|
||||
end
|
||||
|
||||
def case_sensitive_comparison(table, attribute, column, value) # :nodoc:
|
||||
table[attribute].eq(value)
|
||||
def case_sensitive_comparison(attribute, value) # :nodoc:
|
||||
attribute.eq(value)
|
||||
end
|
||||
|
||||
def case_insensitive_comparison(table, attribute, column, value) # :nodoc:
|
||||
def case_insensitive_comparison(attribute, value) # :nodoc:
|
||||
column = column_for_attribute(attribute)
|
||||
|
||||
if can_perform_case_insensitive_comparison_for?(column)
|
||||
table[attribute].lower.eq(table.lower(value))
|
||||
attribute.lower.eq(attribute.relation.lower(value))
|
||||
else
|
||||
table[attribute].eq(value)
|
||||
attribute.eq(value)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -659,6 +661,11 @@ module ActiveRecord
|
|||
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
||||
end
|
||||
|
||||
def column_for_attribute(attribute)
|
||||
table_name = attribute.relation.name
|
||||
schema_cache.columns_hash(table_name)[attribute.name.to_s]
|
||||
end
|
||||
|
||||
def collector
|
||||
if prepared_statements
|
||||
Arel::Collectors::Composite.new(
|
||||
|
|
|
@ -476,9 +476,11 @@ module ActiveRecord
|
|||
SQL
|
||||
end
|
||||
|
||||
def case_sensitive_comparison(table, attribute, column, value) # :nodoc:
|
||||
def case_sensitive_comparison(attribute, value) # :nodoc:
|
||||
column = column_for_attribute(attribute)
|
||||
|
||||
if column.collation && !column.case_sensitive?
|
||||
table[attribute].eq(Arel::Nodes::Bin.new(value))
|
||||
attribute.eq(Arel::Nodes::Bin.new(value))
|
||||
else
|
||||
super
|
||||
end
|
||||
|
|
|
@ -61,28 +61,21 @@ module ActiveRecord
|
|||
value = value.attributes[reflection.klass.primary_key] unless value.nil?
|
||||
end
|
||||
|
||||
if value.nil?
|
||||
return klass.unscoped.where!(attribute => value)
|
||||
relation = klass.unscoped
|
||||
comparison = relation.bind_attribute(attribute, value) do |attr, bind|
|
||||
return relation.none! unless bind.boundable?
|
||||
|
||||
if bind.nil?
|
||||
attr.eq(bind)
|
||||
elsif options[:case_sensitive]
|
||||
klass.connection.case_sensitive_comparison(attr, bind)
|
||||
else
|
||||
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
|
||||
klass.connection.case_insensitive_comparison(attr, bind)
|
||||
end
|
||||
end
|
||||
|
||||
# the attribute may be an aliased attribute
|
||||
if klass.attribute_alias?(attribute)
|
||||
attribute = klass.attribute_alias(attribute)
|
||||
end
|
||||
|
||||
attribute_name = attribute.to_s
|
||||
value = klass.predicate_builder.build_bind_attribute(attribute_name, value)
|
||||
|
||||
table = klass.arel_table
|
||||
column = klass.columns_hash[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.where!(comparison)
|
||||
relation.where!(comparison)
|
||||
end
|
||||
|
||||
def scope_relation(record, relation)
|
||||
|
|
Loading…
Reference in a new issue