Skip to content

Instantly share code, notes, and snippets.

@yepitschunked
Created July 6, 2011 18:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yepitschunked/1067917 to your computer and use it in GitHub Desktop.
Save yepitschunked/1067917 to your computer and use it in GitHub Desktop.
limited eager loading patch
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index c6e8762..56985fa 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -226,16 +226,42 @@ module ActiveRecord
end
def apply_join_dependency(relation, join_dependency)
- join_dependency.join_associations.each do |association|
- relation = association.join_relation(relation)
- end
-
limitable_reflections = using_limitable_reflections?(join_dependency.reflections)
if !limitable_reflections && relation.limit_value
- limited_id_condition = construct_limited_ids_condition(relation.except(:select))
+ # Determine which tables are actually used to limit/sort the result set
+ order_tables = tables_in_string(relation.order_values.join(', ')).map {|t| t.strip if t.respond_to?(:strip)}
+ where_tables = tables_in_string(relation.arel.where_sql).map {|t| t.strip if t.respond_to?(:strip)}
+ all_tables = order_tables + where_tables
+ all_tables.uniq!
+
+ filtering_associations = join_dependency.join_associations.select{|ja| all_tables.include?(ja.aliased_table_name)}
+ all_table_names = filtering_associations.map do |fa|
+ table_names = []
+ node = fa
+ while node.respond_to?(:parent)
+ table_names += node.tables.map(&:name)
+ node = node.parent
+ end
+ table_names << node.aliased_table_name
+ end.flatten.uniq
+
+ # Create a separate relation for use in the DISTINCT query
+ clean_relation = relation.dup
+ for association in join_dependency.join_associations
+ if all_table_names.include?(association.aliased_table_name)
+ clean_relation = association.join_relation(clean_relation)
+ end
+ relation = association.join_relation(relation)
+ end
+
+ limited_id_condition = construct_limited_ids_condition(clean_relation.except(:select))
relation = relation.where(limited_id_condition)
- end
+ else
+ join_dependency.join_associations.each do |association|
+ relation = association.join_relation(relation)
+ end
+ end
relation = relation.except(:limit, :offset) unless limitable_reflections
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment