Browse files

make node search more efficient

Rather than search every node in the tree, comparing that node and all
of its parents every time, start at the root from both sides and work
our way down the tree
  • Loading branch information...
1 parent 9b15db5 commit e73fbdf804633f8e151a33e681f370dfa0fbb3a0 @tenderlove tenderlove committed Oct 9, 2013
View
23 activerecord/lib/active_record/associations/join_dependency.rb
@@ -71,7 +71,7 @@ def graft(*associations)
associations.reject { |association|
join_assocs.detect { |a| node_cmp association, a }
}.each { |association|
- join_node = find_parent_node(association.parent) || @join_root
+ join_node = find_node(association.parent) || @join_root
type = association.join_type
find_or_build_scalar association.reflection, join_node, type
}
@@ -121,11 +121,28 @@ def instantiate(result_set)
private
- def find_parent_node(parent)
- @join_root.find { |join_part| node_cmp parent, join_part }
+ def find_node(target_node)
+ stack = target_node.parents << target_node
+
+ left = [@join_root]
+ right = stack.shift
+
+ loop {
+ match = left.find { |l| l.match? right }
+
+ if match
+ return match if stack.empty?
+
+ left = match.children
+ right = stack.shift
+ else
+ return nil
+ end
+ }
end
def node_cmp(parent, join_part)
+ return true if parent == join_part
return unless parent.class == join_part.class
case parent
View
4 activerecord/lib/active_record/associations/join_dependency/join_association.rb
@@ -33,6 +33,10 @@ def initialize(reflection, index, parent, join_type, alias_tracker)
def parent_table_name; parent.table_name; end
alias :alias_suffix :parent_table_name
+ def match?(other)
+ super && reflection == other.reflection
+ end
+
def join_constraints
joins = []
tables = @tables.dup
View
5 activerecord/lib/active_record/associations/join_dependency/join_base.rb
@@ -8,6 +8,11 @@ def initialize(klass)
super(klass, nil)
end
+ def match?(other)
+ return true if self == other
+ super && base_klass == other.base_klass
+ end
+
def aliased_prefix
"t0"
end
View
14 activerecord/lib/active_record/associations/join_dependency/join_part.rb
@@ -33,6 +33,20 @@ def name
reflection.name
end
+ def match?(other)
+ self.class == other.class
+ end
+
+ def parents
+ parents = []
+ node = parent
+ while node
+ parents.unshift node
+ node = node.parent
+ end
+ parents
+ end
+
def each
yield self
iter = lambda { |list|

0 comments on commit e73fbdf

Please sign in to comment.