Avoid extra query attribute allocation in `_insert_record`/`_update_record`
Since a `BindParam` object always has an attribute object as the value in the Active Record usage, so `_insert_record`/`_update_record` could be passed attribute set instead of wrapping casted value by a query attribute.
This commit is contained in:
parent
adc5eb66f8
commit
6ee96a8f42
|
@ -54,7 +54,6 @@ module ActiveModel
|
|||
|
||||
def write_cast_value(name, value)
|
||||
@attributes[name] = self[name].with_cast_value(value)
|
||||
value
|
||||
end
|
||||
|
||||
def freeze
|
||||
|
|
|
@ -384,9 +384,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def attributes_with_values(attribute_names)
|
||||
attribute_names.index_with do |name|
|
||||
_read_attribute(name)
|
||||
end
|
||||
attribute_names.index_with { |name| @attributes[name] }
|
||||
end
|
||||
|
||||
# Filters the primary keys and readonly attributes from the attribute names.
|
||||
|
|
|
@ -356,27 +356,27 @@ module ActiveRecord
|
|||
primary_key = self.primary_key
|
||||
primary_key_value = nil
|
||||
|
||||
if primary_key && Hash === values
|
||||
primary_key_value = values[primary_key]
|
||||
|
||||
if !primary_key_value && prefetch_primary_key?
|
||||
if prefetch_primary_key? && primary_key
|
||||
values[primary_key] ||= begin
|
||||
primary_key_value = next_sequence_value
|
||||
values[primary_key] = primary_key_value
|
||||
_default_attributes[primary_key].with_cast_value(primary_key_value)
|
||||
end
|
||||
end
|
||||
|
||||
im = Arel::InsertManager.new
|
||||
im.into(arel_table)
|
||||
|
||||
if values.empty?
|
||||
im = arel_table.compile_insert(connection.empty_insert_statement_value(primary_key))
|
||||
im.into arel_table
|
||||
im.insert(connection.empty_insert_statement_value(primary_key))
|
||||
else
|
||||
im = arel_table.compile_insert(_substitute_values(values))
|
||||
im.insert(_substitute_values(values))
|
||||
end
|
||||
|
||||
connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
|
||||
end
|
||||
|
||||
def _update_record(values, constraints) # :nodoc:
|
||||
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
||||
constraints = constraints.map { |name, value| predicate_builder[name, value] }
|
||||
|
||||
if default_scopes?(all_queries: true)
|
||||
constraints << default_scoped(all_queries: true).where_clause.ast
|
||||
|
@ -386,15 +386,16 @@ module ActiveRecord
|
|||
constraints << current_scope.where_clause.ast
|
||||
end
|
||||
|
||||
um = arel_table.where(
|
||||
constraints.reduce(&:and)
|
||||
).compile_update(_substitute_values(values), primary_key)
|
||||
um = Arel::UpdateManager.new
|
||||
um.table(arel_table)
|
||||
um.set(_substitute_values(values))
|
||||
um.wheres = constraints
|
||||
|
||||
connection.update(um, "#{self} Update")
|
||||
end
|
||||
|
||||
def _delete_record(constraints) # :nodoc:
|
||||
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
||||
constraints = constraints.map { |name, value| predicate_builder[name, value] }
|
||||
|
||||
if default_scopes?(all_queries: true)
|
||||
constraints << default_scoped(all_queries: true).where_clause.ast
|
||||
|
@ -430,9 +431,7 @@ module ActiveRecord
|
|||
|
||||
def _substitute_values(values)
|
||||
values.map do |name, value|
|
||||
attr = arel_table[name]
|
||||
bind = predicate_builder.build_bind_attribute(attr.name, value)
|
||||
[attr, bind]
|
||||
[ arel_table[name], Arel::Nodes::BindParam.new(value) ]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -688,8 +687,8 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
update_constraints = _primary_key_constraints_hash
|
||||
attributes.each do |k, v|
|
||||
@attributes.write_cast_value(k, v)
|
||||
attributes = attributes.each_with_object({}) do |(k, v), h|
|
||||
h[k] = @attributes.write_cast_value(k, v)
|
||||
clear_attribute_change(k)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue