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:
David Heinemeier Hansson 2005-04-18 18:49:34 +00:00
parent 3b9bf64130
commit 49d0f0cb66
4 changed files with 52 additions and 52 deletions

View File

@ -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

View File

@ -32,6 +32,10 @@ module ActiveRecord
@loaded
end
def target
@target
end
def target=(t)
@target = t
@loaded = true

View File

@ -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:

View File

@ -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