Speeded up eager loading a whole bunch
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1212 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
3b9bf64130
commit
49d0f0cb66
|
@ -683,34 +683,42 @@ module ActiveRecord
|
|||
schema_abbreviations = generate_schema_abbreviations(reflections)
|
||||
primary_key_table = generate_primary_key_table(reflections, schema_abbreviations)
|
||||
|
||||
rows = select_all_rows(options, schema_abbreviations, reflections)
|
||||
records = extract_and_instantiate_records(schema_abbreviations, rows)
|
||||
|
||||
assign_associations_to_records(rows, records, reflections, schema_abbreviations, primary_key_table)
|
||||
rows = select_all_rows(options, schema_abbreviations, reflections)
|
||||
records = { }
|
||||
primary_key = primary_key_table[table_name]
|
||||
|
||||
for row in rows
|
||||
id = row[primary_key]
|
||||
records[id] ||= instantiate(extract_record(schema_abbreviations, table_name, row))
|
||||
|
||||
return records
|
||||
end
|
||||
|
||||
def assign_associations_to_records(rows, records, reflections, schema_abbreviations, primary_key_table)
|
||||
records.each do |record|
|
||||
reflections.each do |reflection|
|
||||
next unless row[primary_key_table[reflection.table_name]]
|
||||
|
||||
case reflection.macro
|
||||
when :has_many, :has_and_belongs_to_many
|
||||
record.send(reflection.name).target =
|
||||
extract_association_for_record(record, schema_abbreviations, primary_key_table, rows, reflection)
|
||||
records[id].send(reflection.name)
|
||||
records[id].instance_variable_get("@#{reflection.name}").target.push(
|
||||
reflection.klass.send(:instantiate, extract_record(schema_abbreviations, reflection.table_name, row))
|
||||
)
|
||||
when :has_one, :belongs_to
|
||||
record.send(
|
||||
"set_#{reflection.name}_target",
|
||||
extract_association_for_record(record, schema_abbreviations, primary_key_table, rows, reflection).first
|
||||
records[id].send(
|
||||
"#{reflection.name}=",
|
||||
reflection.klass.send(:instantiate, extract_record(schema_abbreviations, reflection.table_name, row))
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return records.values
|
||||
end
|
||||
|
||||
|
||||
def reflect_on_included_associations(associations)
|
||||
[ associations ].flatten.collect { |association| reflect_on_association(association) }
|
||||
end
|
||||
|
||||
def generate_schema_abbreviations(reflections)
|
||||
schema = [ [ table_name, columns.collect { |c| c.name } ] ]
|
||||
schema += reflections.collect { |r| [ r.klass.table_name, r.klass.columns.collect { |c| c.name } ] }
|
||||
schema = [ [ table_name, column_names ] ]
|
||||
schema += reflections.collect { |r| [ r.table_name, r.klass.column_names ] }
|
||||
|
||||
schema_abbreviations = {}
|
||||
schema.each_with_index do |table_and_columns, i|
|
||||
|
@ -736,9 +744,14 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
|
||||
def construct_finder_sql_with_included_associations(options, schema_abbreviations, reflections)
|
||||
habtm_associations = reflections.find_all { |r| r.macro == :has_and_belongs_to_many }
|
||||
def select_all_rows(options, schema_abbreviations, reflections)
|
||||
connection.select_all(
|
||||
construct_finder_sql_with_included_associations(options, schema_abbreviations, reflections),
|
||||
"#{name} Load Including Associations"
|
||||
)
|
||||
end
|
||||
|
||||
def construct_finder_sql_with_included_associations(options, schema_abbreviations, reflections)
|
||||
sql = "SELECT #{column_aliases(schema_abbreviations)} FROM #{table_name} "
|
||||
sql << reflections.collect { |reflection| association_join(reflection) }.to_s
|
||||
sql << "#{options[:joins]} " if options[:joins]
|
||||
|
@ -775,39 +788,14 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
|
||||
def extract_and_instantiate_records(schema_abbreviations, rows)
|
||||
rows.collect { |row| instantiate(extract_record(schema_abbreviations, table_name, row)) }.uniq
|
||||
end
|
||||
|
||||
def extract_association_for_record(record, schema_abbreviations, primary_key_table, rows, reflection)
|
||||
association = rows.collect do |row|
|
||||
if row[primary_key_table[table_name]].to_s == record.id.to_s && !row[primary_key_table[reflection.klass.table_name]].nil?
|
||||
reflection.klass.send(:instantiate, extract_record(schema_abbreviations, reflection.klass.table_name, row))
|
||||
end
|
||||
end
|
||||
|
||||
return association.uniq.compact
|
||||
end
|
||||
|
||||
def extract_record(schema_abbreviations, table_name, row)
|
||||
row.inject({}) do |record, pair|
|
||||
prefix, column_name = schema_abbreviations[pair.first]
|
||||
record[column_name] = pair.last if prefix == table_name
|
||||
record
|
||||
record = {}
|
||||
row.each do |column, value|
|
||||
prefix, column_name = schema_abbreviations[column]
|
||||
record[column_name] = value if prefix == table_name
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def reflect_on_included_associations(associations)
|
||||
[ associations ].flatten.collect { |association| reflect_on_association(association) }
|
||||
end
|
||||
|
||||
def select_all_rows(options, schema_abbreviations, reflections)
|
||||
connection.select_all(
|
||||
construct_finder_sql_with_included_associations(options, schema_abbreviations, reflections),
|
||||
"#{name} Load Including Associations"
|
||||
)
|
||||
end
|
||||
return record
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,10 @@ module ActiveRecord
|
|||
@loaded
|
||||
end
|
||||
|
||||
def target
|
||||
@target
|
||||
end
|
||||
|
||||
def target=(t)
|
||||
@target = t
|
||||
@loaded = true
|
||||
|
|
|
@ -618,6 +618,10 @@ module ActiveRecord #:nodoc:
|
|||
def columns_hash
|
||||
@columns_hash ||= columns.inject({}) { |hash, column| hash[column.name] = column; hash }
|
||||
end
|
||||
|
||||
def column_names
|
||||
@column_names ||= columns_hash.keys
|
||||
end
|
||||
|
||||
# Returns an array of columns objects where the primary id, all columns ending in "_id" or "_count",
|
||||
# and columns used for single table inheritance has been removed.
|
||||
|
@ -640,7 +644,7 @@ module ActiveRecord #:nodoc:
|
|||
|
||||
# Resets all the cached information about columns, which will cause they to be reloaded on the next request.
|
||||
def reset_column_information
|
||||
@columns = @columns_hash = @content_columns = @dynamic_methods_hash = nil
|
||||
@column_names = @columns = @columns_hash = @content_columns = @dynamic_methods_hash = nil
|
||||
end
|
||||
|
||||
def reset_column_information_and_inheritable_attributes_for_all_subclasses#:nodoc:
|
||||
|
|
|
@ -114,7 +114,11 @@ module ActiveRecord
|
|||
# Holds all the meta-data about an association as it was specified in the Active Record class.
|
||||
class AssociationReflection < MacroReflection #:nodoc:
|
||||
def klass
|
||||
active_record.send(:compute_type, (name_to_class_name(name.id2name)))
|
||||
@klass ||= active_record.send(:compute_type, (name_to_class_name(name.id2name)))
|
||||
end
|
||||
|
||||
def table_name
|
||||
@table_name ||= klass.table_name
|
||||
end
|
||||
|
||||
private
|
||||
|
|
Loading…
Reference in New Issue