Permalink
Browse files

Relation optimizing: Add the ability to collapse sequential restricti…

…ons into a single one.
  • Loading branch information...
1 parent e7fb6a9 commit e8d63b0053318b8f7d522bd8d40b174123a1abd1 Carl Lerche committed Mar 23, 2010
View
6 lib/arel/algebra/relations/operations/join.rb
@@ -44,6 +44,12 @@ def join?
def engine
relation1.engine != relation2.engine ? Memory::Engine.new : relation1.engine
end
+
+ def root_engine
+ if relation1.respond_to?(:engine) && relation2.respond_to?(:engine)
+ relation1.engine == relation2.engine && relation1.engine
+ end
+ end
end
class InnerJoin < Join; end
View
26 lib/arel/algebra/relations/operations/where.rb
@@ -1,4 +1,5 @@
module Arel
+ # TODO: Where should be renamed to Restriction
class Where < Compound
attributes :relation, :predicates
deriving :==
@@ -13,5 +14,30 @@ def initialize(relation, *predicates, &block)
def wheres
@wheres ||= relation.wheres + predicates
end
+
+ def optimized
+ case relation
+ when Where then collapse_restrictions
+ else
+ super
+ end
+ end
+
+ private
+
+ def collapse_restrictions
+ collapsed = Where.new(relation.relation, relation.predicates + predicates)
+
+ # That was easy
+ return collapsed.optimized if engine_handles?(collapsed)
+
+ # Swap the relations if needed
+ if engine_handles?(self) && !engine_handles?(relation)
+ Where.new(Where.new(relation.relation, predicates), relation.predicates).optimized
+ else
+ self
+ end
+ end
+
end
end
View
12 lib/arel/algebra/relations/relation.rb
@@ -14,6 +14,18 @@ def bind(relation)
self
end
+ def root_engine
+ engine
+ end
+
+ def engine_handles?(relation)
+ root_engine.nil? || !root_engine.respond_to?(:handles?) || root_engine.handles?(relation)
+ end
+
+ def optimized
+ self
+ end
+
module Enumerable
include ::Enumerable
View
6 lib/arel/algebra/relations/utilities/compound.rb
@@ -34,11 +34,7 @@ def engine
engine = relation.engine
# Temporary check of whether or not the engine supports where.
- if requires && engine.respond_to?(:supports) && !engine.supports(requires)
- Memory::Engine.new
- else
- engine
- end
+ engine_handles?(self) ? engine : Memory::Engine.new
end
private
View
12 lib/arel/algebra/relations/writes.rb
@@ -6,6 +6,10 @@ class Deletion < Compound
def call
engine.delete(self)
end
+
+ def engine_handles?(relation)
+ true
+ end
end
class Insert < Compound
@@ -19,6 +23,10 @@ def initialize(relation, record)
def call
engine.create(self)
end
+
+ def engine_handles?(relation)
+ true
+ end
end
class Update < Compound
@@ -32,5 +40,9 @@ def initialize(relation, assignments)
def call
engine.update(self)
end
+
+ def engine_handles?(relation)
+ true
+ end
end
end
View
2 lib/arel/engines/sql/relations/utilities/compound.rb
@@ -1,6 +1,6 @@
module Arel
class Compound
- delegate :table, :table_sql, :to => :relation
+ delegate :table, :table_sql, :root_engine, :to => :relation
def build_query(*parts)
parts.compact.join(" ")
View
2 spec/support/model.rb
@@ -7,7 +7,7 @@ def initialize
@rows = []
end
- def supports(operation)
+ def handles?(relation)
false
end

0 comments on commit e8d63b0

Please sign in to comment.