From 7032a50297fce4d7724d1735e81e5df5fd919e71 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 14:31:04 -0400
Subject: reorganized file structures

Conflicts:

	lib/arel.rb
	lib/arel/arel.rb
	lib/arel/engines/memory/predicates.rb
	lib/arel/engines/memory/relations/array.rb
	lib/arel/engines/sql/relations/table.rb
---
 lib/arel/algebra/extensions.rb                     |   4 +
 lib/arel/algebra/extensions/array.rb               |   5 +
 lib/arel/algebra/extensions/class.rb               |  37 ++++++
 lib/arel/algebra/extensions/hash.rb                |   7 ++
 lib/arel/algebra/extensions/object.rb              |  15 +++
 lib/arel/algebra/extensions/pathname.rb            |   5 +
 lib/arel/algebra/predicates.rb                     |  45 +++++++
 lib/arel/algebra/primitives.rb                     |   4 +
 lib/arel/algebra/primitives/attribute.rb           | 133 ++++++++++++++++++++
 lib/arel/algebra/primitives/expression.rb          |  31 +++++
 lib/arel/algebra/primitives/value.rb               |  19 +++
 lib/arel/algebra/relations.rb                      |  15 +++
 lib/arel/algebra/relations/operations/alias.rb     |   7 ++
 lib/arel/algebra/relations/operations/group.rb     |  15 +++
 lib/arel/algebra/relations/operations/join.rb      |  41 +++++++
 lib/arel/algebra/relations/operations/order.rb     |  16 +++
 lib/arel/algebra/relations/operations/project.rb   |  19 +++
 lib/arel/algebra/relations/operations/skip.rb      |  10 ++
 lib/arel/algebra/relations/operations/take.rb      |  10 ++
 lib/arel/algebra/relations/operations/where.rb     |  16 +++
 lib/arel/algebra/relations/relation.rb             | 134 +++++++++++++++++++++
 lib/arel/algebra/relations/utilities/compound.rb   |  18 +++
 .../algebra/relations/utilities/externalization.rb |  24 ++++
 lib/arel/algebra/relations/utilities/nil.rb        |   7 ++
 lib/arel/algebra/relations/writes/delete.rb        |  10 ++
 lib/arel/algebra/relations/writes/insert.rb        |  14 +++
 lib/arel/algebra/relations/writes/update.rb        |  14 +++
 27 files changed, 675 insertions(+)
 create mode 100644 lib/arel/algebra/extensions.rb
 create mode 100644 lib/arel/algebra/extensions/array.rb
 create mode 100644 lib/arel/algebra/extensions/class.rb
 create mode 100644 lib/arel/algebra/extensions/hash.rb
 create mode 100644 lib/arel/algebra/extensions/object.rb
 create mode 100644 lib/arel/algebra/extensions/pathname.rb
 create mode 100644 lib/arel/algebra/predicates.rb
 create mode 100644 lib/arel/algebra/primitives.rb
 create mode 100644 lib/arel/algebra/primitives/attribute.rb
 create mode 100644 lib/arel/algebra/primitives/expression.rb
 create mode 100644 lib/arel/algebra/primitives/value.rb
 create mode 100644 lib/arel/algebra/relations.rb
 create mode 100644 lib/arel/algebra/relations/operations/alias.rb
 create mode 100644 lib/arel/algebra/relations/operations/group.rb
 create mode 100644 lib/arel/algebra/relations/operations/join.rb
 create mode 100644 lib/arel/algebra/relations/operations/order.rb
 create mode 100644 lib/arel/algebra/relations/operations/project.rb
 create mode 100644 lib/arel/algebra/relations/operations/skip.rb
 create mode 100644 lib/arel/algebra/relations/operations/take.rb
 create mode 100644 lib/arel/algebra/relations/operations/where.rb
 create mode 100644 lib/arel/algebra/relations/relation.rb
 create mode 100644 lib/arel/algebra/relations/utilities/compound.rb
 create mode 100644 lib/arel/algebra/relations/utilities/externalization.rb
 create mode 100644 lib/arel/algebra/relations/utilities/nil.rb
 create mode 100644 lib/arel/algebra/relations/writes/delete.rb
 create mode 100644 lib/arel/algebra/relations/writes/insert.rb
 create mode 100644 lib/arel/algebra/relations/writes/update.rb

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions.rb b/lib/arel/algebra/extensions.rb
new file mode 100644
index 0000000000..5338fee989
--- /dev/null
+++ b/lib/arel/algebra/extensions.rb
@@ -0,0 +1,4 @@
+require 'arel/algebra/extensions/object'
+require 'arel/algebra/extensions/class'
+require 'arel/algebra/extensions/array'
+require 'arel/algebra/extensions/hash'
diff --git a/lib/arel/algebra/extensions/array.rb b/lib/arel/algebra/extensions/array.rb
new file mode 100644
index 0000000000..5b6d6d6abd
--- /dev/null
+++ b/lib/arel/algebra/extensions/array.rb
@@ -0,0 +1,5 @@
+class Array
+  def to_hash
+    Hash[*flatten]
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/extensions/class.rb b/lib/arel/algebra/extensions/class.rb
new file mode 100644
index 0000000000..f37898e7d7
--- /dev/null
+++ b/lib/arel/algebra/extensions/class.rb
@@ -0,0 +1,37 @@
+class Class
+  def attributes(*attrs)
+    @attributes = attrs
+    attr_reader *attrs
+  end
+  
+  def deriving(*methods)
+    methods.each { |m| derive m }
+  end
+  
+  def derive(method_name)
+    methods = {
+      :initialize => "
+        def #{method_name}(#{@attributes.join(',')})
+          #{@attributes.collect { |a| "@#{a} = #{a}" }.join("\n")}
+        end
+      ",
+      :== => "
+        def ==(other)
+          #{name} === other &&
+          #{@attributes.collect { |a| "@#{a} == other.#{a}" }.join(" &&\n")}
+        end
+      "
+    }
+    class_eval methods[method_name], __FILE__, __LINE__
+  end
+  
+  def hash_on(delegatee)
+    define_method :eql? do |other|
+      self == other
+    end
+    
+    define_method :hash do
+      @hash ||= delegatee.hash
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/extensions/hash.rb b/lib/arel/algebra/extensions/hash.rb
new file mode 100644
index 0000000000..7472b5aa73
--- /dev/null
+++ b/lib/arel/algebra/extensions/hash.rb
@@ -0,0 +1,7 @@
+class Hash
+  def bind(relation)
+    inject({}) do |bound, (key, value)|
+      bound.merge(key.bind(relation) => value.bind(relation))
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/extensions/object.rb b/lib/arel/algebra/extensions/object.rb
new file mode 100644
index 0000000000..d626407dcb
--- /dev/null
+++ b/lib/arel/algebra/extensions/object.rb
@@ -0,0 +1,15 @@
+class Object
+  def bind(relation)
+    Arel::Value.new(self, relation)
+  end
+
+  def find_correlate_in(relation)
+    bind(relation)
+  end
+
+  def metaclass
+    class << self
+      self
+    end
+  end
+end
diff --git a/lib/arel/algebra/extensions/pathname.rb b/lib/arel/algebra/extensions/pathname.rb
new file mode 100644
index 0000000000..2f7e2733e7
--- /dev/null
+++ b/lib/arel/algebra/extensions/pathname.rb
@@ -0,0 +1,5 @@
+class Pathname
+  def /(path)
+    (self + path).expand_path
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/predicates.rb b/lib/arel/algebra/predicates.rb
new file mode 100644
index 0000000000..f83101306e
--- /dev/null
+++ b/lib/arel/algebra/predicates.rb
@@ -0,0 +1,45 @@
+module Arel
+  class Predicate
+  end
+
+  class Binary < Predicate
+    attributes :operand1, :operand2
+    deriving :initialize
+
+    def ==(other)
+      self.class === other          and
+      @operand1  ==  other.operand1 and
+      @operand2  ==  other.operand2
+    end
+
+    def bind(relation)
+      self.class.new(operand1.find_correlate_in(relation), operand2.find_correlate_in(relation))
+    end
+  end
+
+  class Equality < Binary
+    def ==(other)
+      Equality === other and
+        ((operand1 == other.operand1 and operand2 == other.operand2) or
+         (operand1 == other.operand2 and operand2 == other.operand1))
+    end
+  end
+
+  class GreaterThanOrEqualTo < Binary
+  end
+
+  class GreaterThan < Binary
+  end
+
+  class LessThanOrEqualTo < Binary
+  end
+
+  class LessThan < Binary
+  end
+
+  class Match < Binary
+  end
+
+  class In < Binary
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/primitives.rb b/lib/arel/algebra/primitives.rb
new file mode 100644
index 0000000000..a4c3169e0b
--- /dev/null
+++ b/lib/arel/algebra/primitives.rb
@@ -0,0 +1,4 @@
+require 'arel/algebra/primitives/attribute'
+require 'arel/algebra/primitives/value'
+require 'arel/algebra/primitives/expression'
+
diff --git a/lib/arel/algebra/primitives/attribute.rb b/lib/arel/algebra/primitives/attribute.rb
new file mode 100644
index 0000000000..5e216770e4
--- /dev/null
+++ b/lib/arel/algebra/primitives/attribute.rb
@@ -0,0 +1,133 @@
+require 'set'
+
+module Arel
+  class Attribute
+    attributes :relation, :name, :alias, :ancestor
+    deriving :==
+    delegate :engine, :christener, :to => :relation
+
+    def initialize(relation, name, options = {})
+      @relation, @name, @alias, @ancestor = relation, name, options[:alias], options[:ancestor]
+    end
+
+    def named?(hypothetical_name)
+      (@alias || name).to_s == hypothetical_name.to_s
+    end
+
+    def aggregation?
+      false
+    end
+
+    module Transformations
+      def self.included(klass)
+        klass.send :alias_method, :eql?, :==
+      end
+
+      def hash
+        @hash ||= history.size + name.hash + relation.hash
+      end
+
+      def as(aliaz = nil)
+        Attribute.new(relation, name, :alias => aliaz, :ancestor => self)
+      end
+
+      def bind(new_relation)
+        relation == new_relation ? self : Attribute.new(new_relation, name, :alias => @alias, :ancestor => self)
+      end
+
+      def to_attribute
+        self
+      end
+    end
+    include Transformations
+
+    module Congruence
+      def history
+        @history ||= [self] + (ancestor ? ancestor.history : [])
+      end
+
+      def join?
+        relation.join?
+      end
+
+      def root
+        history.last
+      end
+
+      def original_relation
+        @original_relation ||= original_attribute.relation
+      end
+
+      def original_attribute
+        @original_attribute ||= history.detect { |a| !a.join? }
+      end
+
+      def find_correlate_in(relation)
+        relation[self] || self
+      end
+
+      def descends_from?(other)
+        history.include?(other)
+      end
+
+      def /(other)
+        other ? (history & other.history).size : 0
+      end
+    end
+    include Congruence
+
+    module Predications
+      def eq(other)
+        Equality.new(self, other)
+      end
+
+      def lt(other)
+        LessThan.new(self, other)
+      end
+
+      def lteq(other)
+        LessThanOrEqualTo.new(self, other)
+      end
+
+      def gt(other)
+        GreaterThan.new(self, other)
+      end
+
+      def gteq(other)
+        GreaterThanOrEqualTo.new(self, other)
+      end
+
+      def matches(regexp)
+        Match.new(self, regexp)
+      end
+
+      def in(array)
+        In.new(self, array)
+      end
+    end
+    include Predications
+
+    module Expressions
+      def count(distinct = false)
+        distinct ?  Expression.new(self, "DISTINCT").count :  Expression.new(self, "COUNT")
+      end
+
+      def sum
+        Expression.new(self, "SUM")
+      end
+
+      def maximum
+        Expression.new(self, "MAX")
+      end
+
+      def minimum
+        Expression.new(self, "MIN")
+      end
+
+      def average
+        Expression.new(self, "AVG")
+      end
+    end
+    include Expressions
+  end
+end
diff --git a/lib/arel/algebra/primitives/expression.rb b/lib/arel/algebra/primitives/expression.rb
new file mode 100644
index 0000000000..b67a5e1f8e
--- /dev/null
+++ b/lib/arel/algebra/primitives/expression.rb
@@ -0,0 +1,31 @@
+module Arel
+  class Expression < Attribute
+    attributes :attribute, :function_sql, :alias, :ancestor
+    deriving :==
+    delegate :relation, :to => :attribute
+    alias_method :name, :alias
+
+    def initialize(attribute, function_sql, aliaz = nil, ancestor = nil)
+      @attribute, @function_sql, @alias, @ancestor = attribute, function_sql, aliaz, ancestor
+    end
+
+    def aggregation?
+      true
+    end
+
+    module Transformations
+      def as(aliaz)
+        Expression.new(attribute, function_sql, aliaz, self)
+      end
+
+      def bind(new_relation)
+        new_relation == relation ? self : Expression.new(attribute.bind(new_relation), function_sql, @alias, self)
+      end
+
+      def to_attribute
+        Attribute.new(relation, @alias, :ancestor => self)
+      end
+    end
+    include Transformations
+  end
+end
diff --git a/lib/arel/algebra/primitives/value.rb b/lib/arel/algebra/primitives/value.rb
new file mode 100644
index 0000000000..91c4045507
--- /dev/null
+++ b/lib/arel/algebra/primitives/value.rb
@@ -0,0 +1,19 @@
+module Arel
+  class Value
+    attributes :value, :relation
+    deriving :initialize, :==
+    delegate :inclusion_predicate_sql, :equality_predicate_sql, :to => :value
+
+    def bind(relation)
+      Value.new(value, relation)
+    end
+
+    def aggregation?
+      false
+    end
+
+    def to_attribute
+      value
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations.rb b/lib/arel/algebra/relations.rb
new file mode 100644
index 0000000000..03f04d2459
--- /dev/null
+++ b/lib/arel/algebra/relations.rb
@@ -0,0 +1,15 @@
+require 'arel/algebra/relations/relation'
+require 'arel/algebra/relations/utilities/compound'
+require 'arel/algebra/relations/utilities/nil'
+require 'arel/algebra/relations/utilities/externalization'
+require 'arel/algebra/relations/writes/delete'
+require 'arel/algebra/relations/writes/update'
+require 'arel/algebra/relations/writes/insert'
+require 'arel/algebra/relations/operations/alias'
+require 'arel/algebra/relations/operations/group'
+require 'arel/algebra/relations/operations/join'
+require 'arel/algebra/relations/operations/order'
+require 'arel/algebra/relations/operations/project'
+require 'arel/algebra/relations/operations/where'
+require 'arel/algebra/relations/operations/skip'
+require 'arel/algebra/relations/operations/take'
\ No newline at end of file
diff --git a/lib/arel/algebra/relations/operations/alias.rb b/lib/arel/algebra/relations/operations/alias.rb
new file mode 100644
index 0000000000..67837f6a75
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/alias.rb
@@ -0,0 +1,7 @@
+module Arel
+  class Alias < Compound
+    attributes :relation
+    deriving :initialize
+    alias_method :==, :equal?
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations/operations/group.rb b/lib/arel/algebra/relations/operations/group.rb
new file mode 100644
index 0000000000..04fd9fea62
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/group.rb
@@ -0,0 +1,15 @@
+module Arel
+  class Group < Compound
+    attributes :relation, :groupings
+    deriving :==
+
+    def initialize(relation, *groupings, &block)
+      @relation = relation
+      @groupings = (groupings + (block_given?? [yield(relatoin)] : [])).collect { |g| g.bind(relation) }
+    end
+
+    def externalizable?
+      true
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations/operations/join.rb b/lib/arel/algebra/relations/operations/join.rb
new file mode 100644
index 0000000000..8e19254378
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/join.rb
@@ -0,0 +1,41 @@
+module Arel
+  class Join < Relation
+    attributes :join_sql, :relation1, :relation2, :predicates
+    deriving :==
+    delegate :engine, :name, :to => :relation1
+    hash_on :relation1
+
+    def initialize(join_sql, relation1, relation2 = Nil.instance, *predicates)
+      @join_sql, @relation1, @relation2, @predicates = join_sql, relation1, relation2, predicates
+    end
+
+    def attributes
+      @attributes ||= (relation1.externalize.attributes +
+        relation2.externalize.attributes).collect { |a| a.bind(self) }
+    end
+
+    def wheres
+      # TESTME bind to self?
+      relation1.externalize.wheres
+    end
+
+    def ons
+      @ons ||= @predicates.collect { |p| p.bind(self) }
+    end
+
+    # TESTME
+    def externalizable?
+      relation1.externalizable? or relation2.externalizable?
+    end
+
+    def join?
+      true
+    end
+  end
+
+  class Relation
+    def join?
+      false
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations/operations/order.rb b/lib/arel/algebra/relations/operations/order.rb
new file mode 100644
index 0000000000..05af3fde4d
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/order.rb
@@ -0,0 +1,16 @@
+module Arel
+  class Order < Compound
+    attributes :relation, :orderings
+    deriving :==
+    
+    def initialize(relation, *orderings, &block)
+      @relation = relation
+      @orderings = (orderings + (block_given?? [yield(relation)] : [])).collect { |o| o.bind(relation) }
+    end
+
+    # TESTME
+    def orders
+      (orderings + relation.orders).collect { |o| o.bind(self) }
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations/operations/project.rb b/lib/arel/algebra/relations/operations/project.rb
new file mode 100644
index 0000000000..5507ea3163
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/project.rb
@@ -0,0 +1,19 @@
+module Arel
+  class Project < Compound
+    attributes :relation, :projections
+    deriving :==
+
+    def initialize(relation, *projections, &block)
+      @relation = relation
+      @projections = (projections + (block_given?? [yield(relation)] : [])).collect { |p| p.bind(relation) }
+    end
+
+    def attributes
+      @attributes ||= projections.collect { |p| p.bind(self) }
+    end
+
+    def externalizable?
+      attributes.any?(&:aggregation?) or relation.externalizable?
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations/operations/skip.rb b/lib/arel/algebra/relations/operations/skip.rb
new file mode 100644
index 0000000000..930e4c94ea
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/skip.rb
@@ -0,0 +1,10 @@
+module Arel
+  class Skip < Compound
+    attributes :relation, :skipped
+    deriving :initialize, :==
+    
+    def externalizable?
+      true
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations/operations/take.rb b/lib/arel/algebra/relations/operations/take.rb
new file mode 100644
index 0000000000..2fd3fdf635
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/take.rb
@@ -0,0 +1,10 @@
+module Arel
+  class Take < Compound
+    attributes :relation, :taken
+    deriving :initialize, :==
+    
+    def externalizable?
+      true
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations/operations/where.rb b/lib/arel/algebra/relations/operations/where.rb
new file mode 100644
index 0000000000..608aaeb4b7
--- /dev/null
+++ b/lib/arel/algebra/relations/operations/where.rb
@@ -0,0 +1,16 @@
+module Arel
+  class Where < Compound
+    attributes :relation, :predicate
+    deriving :==
+
+    def initialize(relation, *predicates, &block)
+      predicate = block_given?? yield(relation) : predicates.shift
+      @relation = predicates.empty?? relation : Where.new(relation, *predicates)
+      @predicate = predicate.bind(@relation)
+    end
+
+    def wheres
+      @wheres ||= (relation.wheres + [predicate]).collect { |p| p.bind(self) }
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations/relation.rb b/lib/arel/algebra/relations/relation.rb
new file mode 100644
index 0000000000..20badaf165
--- /dev/null
+++ b/lib/arel/algebra/relations/relation.rb
@@ -0,0 +1,134 @@
+module Arel
+  class Relation
+    attr_reader :count
+
+    def session
+      Session.new
+    end
+
+    def call
+      engine.read(self)
+    end
+
+    def bind(relation)
+      self
+    end
+
+    def root
+      self
+    end
+
+    module Enumerable
+      include ::Enumerable
+
+      def each(&block)
+        session.read(self).each(&block)
+      end
+
+      def first
+        session.read(self).first
+      end
+    end
+    include Enumerable
+
+    module Operable
+      def join(other_relation = nil, join_type = "INNER JOIN")
+        case other_relation
+        when String
+          Join.new(other_relation, self)
+        when Relation
+          JoinOperation.new(join_type, self, other_relation)
+        else
+          self
+        end
+      end
+
+      def outer_join(other_relation = nil)
+        join(other_relation, "LEFT OUTER JOIN")
+      end
+
+      [:where, :project, :order, :take, :skip, :group].each do |operation_name|
+        operation = <<-OPERATION
+          def #{operation_name}(*arguments, &block)
+            arguments.all?(&:blank?) && !block_given?? self : #{operation_name.to_s.classify}.new(self, *arguments, &block)
+          end
+        OPERATION
+        class_eval operation, __FILE__, __LINE__
+      end
+
+      def alias
+        Alias.new(self)
+      end
+
+      module Writable
+        def insert(record)
+          session.create Insert.new(self, record); self
+        end
+
+        def update(assignments)
+          session.update Update.new(self, assignments)
+        end
+
+        def delete
+          session.delete Deletion.new(self)
+        end
+      end
+      include Writable
+
+      JoinOperation = Struct.new(:join_sql, :relation1, :relation2) do
+        def on(*predicates)
+          Join.new(join_sql, relation1, relation2, *predicates)
+        end
+      end
+    end
+    include Operable
+
+    module AttributeAccessable
+      def [](index)
+        case index
+        when Symbol, String
+          find_attribute_matching_name(index)
+        when Attribute, Expression
+          find_attribute_matching_attribute(index)
+        when Array
+          index.collect { |i| self[i] }
+        end
+      end
+
+      def find_attribute_matching_name(name)
+        attributes.detect { |a| a.named?(name) }
+      end
+
+      def find_attribute_matching_attribute(attribute)
+        matching_attributes(attribute).max do |a1, a2|
+          (a1.original_attribute / attribute) <=> (a2.original_attribute / attribute)
+        end
+      end
+
+      private
+      def matching_attributes(attribute)
+        (@matching_attributes ||= attributes.inject({}) do |hash, a|
+          (hash[a.root] ||= []) << a
+          hash
+        end)[attribute.root] || []
+      end
+
+      def has_attribute?(attribute)
+        !matching_attributes(attribute).empty?
+      end
+    end
+    include AttributeAccessable
+
+    module DefaultOperations
+      def attributes;             []  end
+      def wheres;                 []  end
+      def orders;                 []  end
+      def inserts;                []  end
+      def groupings;              []  end
+      def joins(formatter = nil); nil end # FIXME
+      def taken;                  nil end
+      def skipped;                nil end
+    end
+    include DefaultOperations
+  end
+end
diff --git a/lib/arel/algebra/relations/utilities/compound.rb b/lib/arel/algebra/relations/utilities/compound.rb
new file mode 100644
index 0000000000..e33b8dbf14
--- /dev/null
+++ b/lib/arel/algebra/relations/utilities/compound.rb
@@ -0,0 +1,18 @@
+module Arel
+  class Compound < Relation
+    attr_reader :relation
+    hash_on :relation
+    delegate :joins, :join?, :inserts, :taken, :skipped, :name, :externalizable?,
+             :column_for, :engine, :table, :table_sql, :array,
+             :to => :relation
+
+    [:attributes, :wheres, :groupings, :orders].each do |operation_name|
+      operation = <<-OPERATION
+        def #{operation_name}
+          @#{operation_name} ||= relation.#{operation_name}.collect { |o| o.bind(self) }
+        end
+      OPERATION
+      class_eval operation, __FILE__, __LINE__
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations/utilities/externalization.rb b/lib/arel/algebra/relations/utilities/externalization.rb
new file mode 100644
index 0000000000..bd067f2304
--- /dev/null
+++ b/lib/arel/algebra/relations/utilities/externalization.rb
@@ -0,0 +1,24 @@
+module Arel
+  class Externalization < Compound
+    attributes :relation
+    deriving :initialize, :==
+
+    def wheres
+      []
+    end
+
+    def attributes
+      @attributes ||= relation.attributes.collect(&:to_attribute).collect { |a| a.bind(self) }
+    end
+  end
+
+  class Relation
+    def externalize
+      @externalized ||= externalizable?? Externalization.new(self) : self
+    end
+
+    def externalizable?
+      false
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations/utilities/nil.rb b/lib/arel/algebra/relations/utilities/nil.rb
new file mode 100644
index 0000000000..6a9d678c45
--- /dev/null
+++ b/lib/arel/algebra/relations/utilities/nil.rb
@@ -0,0 +1,7 @@
+require 'singleton'
+
+module Arel
+  class Nil < Relation
+    include Singleton
+  end
+end
diff --git a/lib/arel/algebra/relations/writes/delete.rb b/lib/arel/algebra/relations/writes/delete.rb
new file mode 100644
index 0000000000..a94067c7fa
--- /dev/null
+++ b/lib/arel/algebra/relations/writes/delete.rb
@@ -0,0 +1,10 @@
+module Arel
+  class Deletion < Compound
+    attributes :relation
+    deriving :initialize, :==
+
+    def call
+      engine.delete(self)
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations/writes/insert.rb b/lib/arel/algebra/relations/writes/insert.rb
new file mode 100644
index 0000000000..6d85e9769a
--- /dev/null
+++ b/lib/arel/algebra/relations/writes/insert.rb
@@ -0,0 +1,14 @@
+module Arel
+  class Insert < Compound
+    attributes :relation, :record
+    deriving :==
+
+    def initialize(relation, record)
+      @relation, @record = relation, record.bind(relation)
+    end
+
+    def call
+      engine.create(self)
+    end
+  end
+end
diff --git a/lib/arel/algebra/relations/writes/update.rb b/lib/arel/algebra/relations/writes/update.rb
new file mode 100644
index 0000000000..e647218a80
--- /dev/null
+++ b/lib/arel/algebra/relations/writes/update.rb
@@ -0,0 +1,14 @@
+module Arel
+  class Update < Compound
+    attributes :relation, :assignments
+    deriving :==
+
+    def initialize(relation, assignments)
+      @relation, @assignments = relation, assignments
+    end
+
+    def call
+      engine.update(self)
+    end
+  end
+end
-- 
cgit v1.2.3


From b0a45d52fdb7d8ce564f4dc2013bc790f98f1da3 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 14:38:09 -0400
Subject: consolidated files

Conflicts:

	lib/arel/algebra/predicates.rb
	lib/arel/algebra/relations/writes/delete.rb
	lib/arel/algebra/relations/writes/insert.rb
	lib/arel/algebra/relations/writes/update.rb
	lib/arel/engines/memory/predicates.rb
	lib/arel/engines/memory/relations.rb
	lib/arel/engines/sql/primitives/attribute.rb
	lib/arel/engines/sql/relations/writes/insert.rb
	lib/arel/engines/sql/relations/writes/update.rb
---
 lib/arel/algebra/predicates.rb              | 30 +++++++++++-------------
 lib/arel/algebra/relations.rb               |  4 +---
 lib/arel/algebra/relations/writes.rb        | 36 +++++++++++++++++++++++++++++
 lib/arel/algebra/relations/writes/delete.rb | 10 --------
 lib/arel/algebra/relations/writes/insert.rb | 14 -----------
 lib/arel/algebra/relations/writes/update.rb | 14 -----------
 6 files changed, 50 insertions(+), 58 deletions(-)
 create mode 100644 lib/arel/algebra/relations/writes.rb
 delete mode 100644 lib/arel/algebra/relations/writes/delete.rb
 delete mode 100644 lib/arel/algebra/relations/writes/insert.rb
 delete mode 100644 lib/arel/algebra/relations/writes/update.rb

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/predicates.rb b/lib/arel/algebra/predicates.rb
index f83101306e..7f093ded6d 100644
--- a/lib/arel/algebra/predicates.rb
+++ b/lib/arel/algebra/predicates.rb
@@ -1,5 +1,12 @@
 module Arel
   class Predicate
+    def or(other_predicate)
+      Or.new(self, other_predicate)
+    end
+
+    def and(other_predicate)
+      And.new(self, other_predicate)
+    end
   end
 
   class Binary < Predicate
@@ -25,21 +32,10 @@ module Arel
     end
   end
 
-  class GreaterThanOrEqualTo < Binary
-  end
-
-  class GreaterThan < Binary
-  end
-
-  class LessThanOrEqualTo < Binary
-  end
-
-  class LessThan < Binary
-  end
-
-  class Match < Binary
-  end
-
-  class In < Binary
-  end
+  class GreaterThanOrEqualTo  < Binary; end
+  class GreaterThan           < Binary; end
+  class LessThanOrEqualTo     < Binary; end
+  class LessThan              < Binary; end
+  class Match                 < Binary; end
+  class In                    < Binary; end
 end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations.rb b/lib/arel/algebra/relations.rb
index 03f04d2459..b75a31e5e3 100644
--- a/lib/arel/algebra/relations.rb
+++ b/lib/arel/algebra/relations.rb
@@ -2,9 +2,7 @@ require 'arel/algebra/relations/relation'
 require 'arel/algebra/relations/utilities/compound'
 require 'arel/algebra/relations/utilities/nil'
 require 'arel/algebra/relations/utilities/externalization'
-require 'arel/algebra/relations/writes/delete'
-require 'arel/algebra/relations/writes/update'
-require 'arel/algebra/relations/writes/insert'
+require 'arel/algebra/relations/writes'
 require 'arel/algebra/relations/operations/alias'
 require 'arel/algebra/relations/operations/group'
 require 'arel/algebra/relations/operations/join'
diff --git a/lib/arel/algebra/relations/writes.rb b/lib/arel/algebra/relations/writes.rb
new file mode 100644
index 0000000000..352f7bc7e5
--- /dev/null
+++ b/lib/arel/algebra/relations/writes.rb
@@ -0,0 +1,36 @@
+module Arel
+  class Deletion < Compound
+    attributes :relation
+    deriving :initialize, :==
+    
+    def call
+      engine.delete(self)
+    end
+  end
+
+  class Insert < Compound
+    attributes :relation, :record
+    deriving :==
+
+    def initialize(relation, record)
+      @relation, @record = relation, record.bind(relation)
+    end
+    
+    def call
+      engine.create(self)
+    end
+  end
+
+  class Update < Compound
+    attributes :relation, :assignments
+    deriving :==
+    
+    def initialize(relation, assignments)
+      @relation, @assignments = relation, assignments.bind(relation)
+    end
+    
+    def call
+      engine.update(self)
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations/writes/delete.rb b/lib/arel/algebra/relations/writes/delete.rb
deleted file mode 100644
index a94067c7fa..0000000000
--- a/lib/arel/algebra/relations/writes/delete.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-module Arel
-  class Deletion < Compound
-    attributes :relation
-    deriving :initialize, :==
-
-    def call
-      engine.delete(self)
-    end
-  end
-end
diff --git a/lib/arel/algebra/relations/writes/insert.rb b/lib/arel/algebra/relations/writes/insert.rb
deleted file mode 100644
index 6d85e9769a..0000000000
--- a/lib/arel/algebra/relations/writes/insert.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-module Arel
-  class Insert < Compound
-    attributes :relation, :record
-    deriving :==
-
-    def initialize(relation, record)
-      @relation, @record = relation, record.bind(relation)
-    end
-
-    def call
-      engine.create(self)
-    end
-  end
-end
diff --git a/lib/arel/algebra/relations/writes/update.rb b/lib/arel/algebra/relations/writes/update.rb
deleted file mode 100644
index e647218a80..0000000000
--- a/lib/arel/algebra/relations/writes/update.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-module Arel
-  class Update < Compound
-    attributes :relation, :assignments
-    deriving :==
-
-    def initialize(relation, assignments)
-      @relation, @assignments = relation, assignments
-    end
-
-    def call
-      engine.update(self)
-    end
-  end
-end
-- 
cgit v1.2.3


From 892337509b2bd269920dc567bc48c6a28c7222d2 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 14:46:08 -0400
Subject: removed function_sql in favor of polymorphism

Conflicts:

	lib/arel/algebra/primitives/attribute.rb
	lib/arel/algebra/primitives/expression.rb
	spec/arel/unit/primitives/expression_spec.rb
---
 lib/arel/algebra/primitives/attribute.rb  | 10 +++++-----
 lib/arel/algebra/primitives/expression.rb | 18 +++++++++++++-----
 2 files changed, 18 insertions(+), 10 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/primitives/attribute.rb b/lib/arel/algebra/primitives/attribute.rb
index 5e216770e4..943c5b030e 100644
--- a/lib/arel/algebra/primitives/attribute.rb
+++ b/lib/arel/algebra/primitives/attribute.rb
@@ -109,23 +109,23 @@ module Arel
 
     module Expressions
       def count(distinct = false)
-        distinct ?  Expression.new(self, "DISTINCT").count :  Expression.new(self, "COUNT")
+        distinct ?  Distinct.new(self).count :  Count.new(self)
       end
 
       def sum
-        Expression.new(self, "SUM")
+        Sum.new(self)
       end
 
       def maximum
-        Expression.new(self, "MAX")
+        Maximum.new(self)
       end
 
       def minimum
-        Expression.new(self, "MIN")
+        Minimum.new(self)
       end
 
       def average
-        Expression.new(self, "AVG")
+        Average.new(self)
       end
     end
     include Expressions
diff --git a/lib/arel/algebra/primitives/expression.rb b/lib/arel/algebra/primitives/expression.rb
index b67a5e1f8e..989397720c 100644
--- a/lib/arel/algebra/primitives/expression.rb
+++ b/lib/arel/algebra/primitives/expression.rb
@@ -1,12 +1,12 @@
 module Arel
   class Expression < Attribute
-    attributes :attribute, :function_sql, :alias, :ancestor
+    attributes :attribute, :alias, :ancestor
     deriving :==
     delegate :relation, :to => :attribute
     alias_method :name, :alias
 
-    def initialize(attribute, function_sql, aliaz = nil, ancestor = nil)
-      @attribute, @function_sql, @alias, @ancestor = attribute, function_sql, aliaz, ancestor
+    def initialize(attribute, aliaz = nil, ancestor = nil)
+      @attribute, @alias, @ancestor = attribute, aliaz, ancestor
     end
 
     def aggregation?
@@ -15,11 +15,11 @@ module Arel
 
     module Transformations
       def as(aliaz)
-        Expression.new(attribute, function_sql, aliaz, self)
+        self.class.new(attribute, aliaz, self)
       end
 
       def bind(new_relation)
-        new_relation == relation ? self : Expression.new(attribute.bind(new_relation), function_sql, @alias, self)
+        new_relation == relation ? self : self.class.new(attribute.bind(new_relation), @alias, self)
       end
 
       def to_attribute
@@ -28,4 +28,12 @@ module Arel
     end
     include Transformations
   end
+
+  class Count    < Expression; end
+  class Distinct < Expression; end
+  class Sum      < Expression; end
+  class Maximum  < Expression; end
+  class Minimum  < Expression; end
+  class Average  < Expression; end
 end
+
-- 
cgit v1.2.3


From 3a6e8e5a3f99841691b70b89b0a10f836e6ec071 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 14:49:56 -0400
Subject: join sql stuff moved into sql adapter

Conflicts:

	lib/arel/algebra/primitives/value.rb
	lib/arel/algebra/relations/operations/join.rb
	lib/arel/algebra/relations/relation.rb
	spec/arel/unit/relations/join_spec.rb
---
 lib/arel/algebra/primitives/value.rb             |  1 -
 lib/arel/algebra/relations/operations/join.rb    | 14 +++++++++++---
 lib/arel/algebra/relations/relation.rb           | 15 +++++++--------
 lib/arel/algebra/relations/utilities/compound.rb |  3 +--
 4 files changed, 19 insertions(+), 14 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/primitives/value.rb b/lib/arel/algebra/primitives/value.rb
index 91c4045507..76c82890d0 100644
--- a/lib/arel/algebra/primitives/value.rb
+++ b/lib/arel/algebra/primitives/value.rb
@@ -2,7 +2,6 @@ module Arel
   class Value
     attributes :value, :relation
     deriving :initialize, :==
-    delegate :inclusion_predicate_sql, :equality_predicate_sql, :to => :value
 
     def bind(relation)
       Value.new(value, relation)
diff --git a/lib/arel/algebra/relations/operations/join.rb b/lib/arel/algebra/relations/operations/join.rb
index 8e19254378..695f360b51 100644
--- a/lib/arel/algebra/relations/operations/join.rb
+++ b/lib/arel/algebra/relations/operations/join.rb
@@ -1,12 +1,12 @@
 module Arel
   class Join < Relation
-    attributes :join_sql, :relation1, :relation2, :predicates
+    attributes :relation1, :relation2, :predicates
     deriving :==
     delegate :engine, :name, :to => :relation1
     hash_on :relation1
 
-    def initialize(join_sql, relation1, relation2 = Nil.instance, *predicates)
-      @join_sql, @relation1, @relation2, @predicates = join_sql, relation1, relation2, predicates
+    def initialize(relation1, relation2 = Nil.instance, *predicates)
+      @relation1, @relation2, @predicates = relation1, relation2, predicates
     end
 
     def attributes
@@ -33,6 +33,14 @@ module Arel
     end
   end
 
+  class InnerJoin  < Join; end
+  class OuterJoin  < Join; end
+  class StringJoin < Join
+    def attributes
+      relation1.externalize.attributes
+    end
+  end
+
   class Relation
     def join?
       false
diff --git a/lib/arel/algebra/relations/relation.rb b/lib/arel/algebra/relations/relation.rb
index 20badaf165..6d76e66638 100644
--- a/lib/arel/algebra/relations/relation.rb
+++ b/lib/arel/algebra/relations/relation.rb
@@ -32,28 +32,27 @@ module Arel
     include Enumerable
 
     module Operable
-      def join(other_relation = nil, join_type = "INNER JOIN")
+      def join(other_relation = nil, join_class = InnerJoin)
         case other_relation
         when String
-          Join.new(other_relation, self)
+          StringJoin.new(other_relation, self)
         when Relation
-          JoinOperation.new(join_type, self, other_relation)
+          JoinOperation.new(join_class, self, other_relation)
         else
           self
         end
       end
 
       def outer_join(other_relation = nil)
-        join(other_relation, "LEFT OUTER JOIN")
+        join(other_relation, OuterJoin)
       end
 
       [:where, :project, :order, :take, :skip, :group].each do |operation_name|
-        operation = <<-OPERATION
+        class_eval <<-OPERATION, __FILE__, __LINE__
           def #{operation_name}(*arguments, &block)
             arguments.all?(&:blank?) && !block_given?? self : #{operation_name.to_s.classify}.new(self, *arguments, &block)
           end
         OPERATION
-        class_eval operation, __FILE__, __LINE__
       end
 
       def alias
@@ -75,9 +74,9 @@ module Arel
       end
       include Writable
 
-      JoinOperation = Struct.new(:join_sql, :relation1, :relation2) do
+      JoinOperation = Struct.new(:join_class, :relation1, :relation2) do
         def on(*predicates)
-          Join.new(join_sql, relation1, relation2, *predicates)
+          join_class.new(relation1, relation2, *predicates)
         end
       end
     end
diff --git a/lib/arel/algebra/relations/utilities/compound.rb b/lib/arel/algebra/relations/utilities/compound.rb
index e33b8dbf14..fbff36a868 100644
--- a/lib/arel/algebra/relations/utilities/compound.rb
+++ b/lib/arel/algebra/relations/utilities/compound.rb
@@ -7,12 +7,11 @@ module Arel
              :to => :relation
 
     [:attributes, :wheres, :groupings, :orders].each do |operation_name|
-      operation = <<-OPERATION
+      class_eval <<-OPERATION, __FILE__, __LINE__
         def #{operation_name}
           @#{operation_name} ||= relation.#{operation_name}.collect { |o| o.bind(self) }
         end
       OPERATION
-      class_eval operation, __FILE__, __LINE__
     end
   end
 end
-- 
cgit v1.2.3


From 437429764510338bdc5f4915286425f07565a573 Mon Sep 17 00:00:00 2001
From: Nick Kallen <nkallen@nick-kallens-computer-2.local>
Date: Mon, 26 May 2008 14:30:51 -0700
Subject: moved table-related stuff into sql engine

---
 lib/arel/algebra/relations/utilities/compound.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/relations/utilities/compound.rb b/lib/arel/algebra/relations/utilities/compound.rb
index fbff36a868..4d7cece812 100644
--- a/lib/arel/algebra/relations/utilities/compound.rb
+++ b/lib/arel/algebra/relations/utilities/compound.rb
@@ -3,7 +3,7 @@ module Arel
     attr_reader :relation
     hash_on :relation
     delegate :joins, :join?, :inserts, :taken, :skipped, :name, :externalizable?,
-             :column_for, :engine, :table, :table_sql, :array,
+             :column_for, :engine,
              :to => :relation
 
     [:attributes, :wheres, :groupings, :orders].each do |operation_name|
-- 
cgit v1.2.3


From 4e3c9a01307339916f6b947d24f19b0f442afd78 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 14:58:46 -0400
Subject: most in memory operations save join and group

Conflicts:

	lib/arel/algebra/extensions/object.rb
	lib/arel/algebra/primitives/value.rb
	lib/arel/engines/memory/relations.rb
	lib/arel/engines/sql/formatters.rb
	lib/arel/engines/sql/primitives.rb
	spec/arel/unit/relations/alias_spec.rb
	spec/arel/unit/relations/array_spec.rb
	spec/arel/unit/relations/order_spec.rb
---
 lib/arel/algebra/extensions/array.rb           |  7 +++++++
 lib/arel/algebra/extensions/hash.rb            |  7 +++++++
 lib/arel/algebra/extensions/object.rb          |  5 +++++
 lib/arel/algebra/primitives.rb                 |  1 +
 lib/arel/algebra/primitives/attribute.rb       | 17 +++++++++++++++++
 lib/arel/algebra/primitives/ordering.rb        | 18 ++++++++++++++++++
 lib/arel/algebra/primitives/value.rb           |  8 ++------
 lib/arel/algebra/relations/operations/order.rb |  3 ++-
 8 files changed, 59 insertions(+), 7 deletions(-)
 create mode 100644 lib/arel/algebra/primitives/ordering.rb

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions/array.rb b/lib/arel/algebra/extensions/array.rb
index 5b6d6d6abd..935569a07b 100644
--- a/lib/arel/algebra/extensions/array.rb
+++ b/lib/arel/algebra/extensions/array.rb
@@ -2,4 +2,11 @@ class Array
   def to_hash
     Hash[*flatten]
   end
+  
+  def group_by
+    inject({}) do |groups, element|
+      (groups[yield(element)] ||= []) << element
+      groups
+    end
+  end
 end
\ No newline at end of file
diff --git a/lib/arel/algebra/extensions/hash.rb b/lib/arel/algebra/extensions/hash.rb
index 7472b5aa73..bc97785e62 100644
--- a/lib/arel/algebra/extensions/hash.rb
+++ b/lib/arel/algebra/extensions/hash.rb
@@ -4,4 +4,11 @@ class Hash
       bound.merge(key.bind(relation) => value.bind(relation))
     end
   end
+  
+  def slice(*attributes)
+    inject({}) do |cheese, (key, value)|
+      cheese[key] = value if attributes.include?(key)
+      cheese
+    end
+  end
 end
\ No newline at end of file
diff --git a/lib/arel/algebra/extensions/object.rb b/lib/arel/algebra/extensions/object.rb
index d626407dcb..efdbbf525f 100644
--- a/lib/arel/algebra/extensions/object.rb
+++ b/lib/arel/algebra/extensions/object.rb
@@ -12,4 +12,9 @@ class Object
       self
     end
   end
+
+  def let
+    yield(self)
+  end
 end
+
diff --git a/lib/arel/algebra/primitives.rb b/lib/arel/algebra/primitives.rb
index a4c3169e0b..df8d16a5d5 100644
--- a/lib/arel/algebra/primitives.rb
+++ b/lib/arel/algebra/primitives.rb
@@ -1,4 +1,5 @@
 require 'arel/algebra/primitives/attribute'
+require 'arel/algebra/primitives/ordering'
 require 'arel/algebra/primitives/value'
 require 'arel/algebra/primitives/expression'
 
diff --git a/lib/arel/algebra/primitives/attribute.rb b/lib/arel/algebra/primitives/attribute.rb
index 943c5b030e..7a4411e248 100644
--- a/lib/arel/algebra/primitives/attribute.rb
+++ b/lib/arel/algebra/primitives/attribute.rb
@@ -17,6 +17,10 @@ module Arel
     def aggregation?
       false
     end
+    
+    def inspect
+      "<Attribute #{name}>"
+    end
 
     module Transformations
       def self.included(klass)
@@ -129,5 +133,18 @@ module Arel
       end
     end
     include Expressions
+    
+    module Orderings
+      def asc
+        Ascending.new(self)
+      end
+      
+      def desc
+        Descending.new(self)
+      end
+      
+      alias_method :to_ordering, :asc
+    end
+    include Orderings
   end
 end
diff --git a/lib/arel/algebra/primitives/ordering.rb b/lib/arel/algebra/primitives/ordering.rb
new file mode 100644
index 0000000000..e8d8f97188
--- /dev/null
+++ b/lib/arel/algebra/primitives/ordering.rb
@@ -0,0 +1,18 @@
+module Arel
+  class Ordering
+    attributes :attribute
+    deriving :initialize, :==
+    delegate :relation, :to => :attribute
+    
+    def bind(relation)
+      self.class.new(attribute.bind(relation))
+    end
+    
+    def to_ordering
+      self
+    end
+  end
+  
+  class Ascending  < Ordering; end
+  class Descending < Ordering; end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/primitives/value.rb b/lib/arel/algebra/primitives/value.rb
index 76c82890d0..e363805140 100644
--- a/lib/arel/algebra/primitives/value.rb
+++ b/lib/arel/algebra/primitives/value.rb
@@ -7,12 +7,8 @@ module Arel
       Value.new(value, relation)
     end
 
-    def aggregation?
-      false
-    end
-
-    def to_attribute
-      value
+    def to_ordering
+      self
     end
   end
 end
diff --git a/lib/arel/algebra/relations/operations/order.rb b/lib/arel/algebra/relations/operations/order.rb
index 05af3fde4d..eccd8bcda0 100644
--- a/lib/arel/algebra/relations/operations/order.rb
+++ b/lib/arel/algebra/relations/operations/order.rb
@@ -10,7 +10,8 @@ module Arel
 
     # TESTME
     def orders
-      (orderings + relation.orders).collect { |o| o.bind(self) }
+      # QUESTION - do we still need relation.orders ?
+      (orderings + relation.orders).collect { |o| o.bind(self) }.collect { |o| o.to_ordering }
     end
   end
 end
\ No newline at end of file
-- 
cgit v1.2.3


From 9d77c08cf8a75636b058c1b85af52ef96e07cee5 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 15:00:10 -0400
Subject: made block stuff read nicer

Conflicts:

	doc/TODO
---
 lib/arel/algebra/relations/operations/group.rb   | 3 ++-
 lib/arel/algebra/relations/operations/order.rb   | 3 ++-
 lib/arel/algebra/relations/operations/project.rb | 3 ++-
 lib/arel/algebra/relations/utilities/compound.rb | 5 +++++
 4 files changed, 11 insertions(+), 3 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/relations/operations/group.rb b/lib/arel/algebra/relations/operations/group.rb
index 04fd9fea62..879f2352c5 100644
--- a/lib/arel/algebra/relations/operations/group.rb
+++ b/lib/arel/algebra/relations/operations/group.rb
@@ -5,7 +5,8 @@ module Arel
 
     def initialize(relation, *groupings, &block)
       @relation = relation
-      @groupings = (groupings + (block_given?? [yield(relatoin)] : [])).collect { |g| g.bind(relation) }
+      @groupings = (groupings + arguments_from_block(relation, &block)) \
+        .collect { |g| g.bind(relation) }
     end
 
     def externalizable?
diff --git a/lib/arel/algebra/relations/operations/order.rb b/lib/arel/algebra/relations/operations/order.rb
index eccd8bcda0..4e7133f5a8 100644
--- a/lib/arel/algebra/relations/operations/order.rb
+++ b/lib/arel/algebra/relations/operations/order.rb
@@ -5,7 +5,8 @@ module Arel
     
     def initialize(relation, *orderings, &block)
       @relation = relation
-      @orderings = (orderings + (block_given?? [yield(relation)] : [])).collect { |o| o.bind(relation) }
+      @orderings = (orderings + arguments_from_block(relation, &block)) \
+        .collect { |o| o.bind(relation) }
     end
 
     # TESTME
diff --git a/lib/arel/algebra/relations/operations/project.rb b/lib/arel/algebra/relations/operations/project.rb
index 5507ea3163..223d320e22 100644
--- a/lib/arel/algebra/relations/operations/project.rb
+++ b/lib/arel/algebra/relations/operations/project.rb
@@ -5,7 +5,8 @@ module Arel
 
     def initialize(relation, *projections, &block)
       @relation = relation
-      @projections = (projections + (block_given?? [yield(relation)] : [])).collect { |p| p.bind(relation) }
+      @projections = (projections + arguments_from_block(relation, &block)) \
+        .collect { |p| p.bind(relation) }
     end
 
     def attributes
diff --git a/lib/arel/algebra/relations/utilities/compound.rb b/lib/arel/algebra/relations/utilities/compound.rb
index 4d7cece812..99c3d02748 100644
--- a/lib/arel/algebra/relations/utilities/compound.rb
+++ b/lib/arel/algebra/relations/utilities/compound.rb
@@ -13,5 +13,10 @@ module Arel
         end
       OPERATION
     end
+    
+    private
+    def arguments_from_block(relation, &block)
+      block_given?? [yield(relation)] : []
+    end
   end
 end
-- 
cgit v1.2.3


From 8339f024c7663133a78c4d0a8824b5b6fafaf239 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 15:42:42 -0400
Subject: recursive memory operations now possible

Conflicts:

	lib/arel/algebra/relations/relation.rb
---
 lib/arel/algebra/extensions/hash.rb    |  7 -------
 lib/arel/algebra/relations.rb          |  1 +
 lib/arel/algebra/relations/relation.rb |  4 ----
 lib/arel/algebra/relations/row.rb      | 21 +++++++++++++++++++++
 4 files changed, 22 insertions(+), 11 deletions(-)
 create mode 100644 lib/arel/algebra/relations/row.rb

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions/hash.rb b/lib/arel/algebra/extensions/hash.rb
index bc97785e62..7472b5aa73 100644
--- a/lib/arel/algebra/extensions/hash.rb
+++ b/lib/arel/algebra/extensions/hash.rb
@@ -4,11 +4,4 @@ class Hash
       bound.merge(key.bind(relation) => value.bind(relation))
     end
   end
-  
-  def slice(*attributes)
-    inject({}) do |cheese, (key, value)|
-      cheese[key] = value if attributes.include?(key)
-      cheese
-    end
-  end
 end
\ No newline at end of file
diff --git a/lib/arel/algebra/relations.rb b/lib/arel/algebra/relations.rb
index b75a31e5e3..94df5938fe 100644
--- a/lib/arel/algebra/relations.rb
+++ b/lib/arel/algebra/relations.rb
@@ -2,6 +2,7 @@ require 'arel/algebra/relations/relation'
 require 'arel/algebra/relations/utilities/compound'
 require 'arel/algebra/relations/utilities/nil'
 require 'arel/algebra/relations/utilities/externalization'
+require 'arel/algebra/relations/row'
 require 'arel/algebra/relations/writes'
 require 'arel/algebra/relations/operations/alias'
 require 'arel/algebra/relations/operations/group'
diff --git a/lib/arel/algebra/relations/relation.rb b/lib/arel/algebra/relations/relation.rb
index 6d76e66638..fe8cab4b02 100644
--- a/lib/arel/algebra/relations/relation.rb
+++ b/lib/arel/algebra/relations/relation.rb
@@ -14,10 +14,6 @@ module Arel
       self
     end
 
-    def root
-      self
-    end
-
     module Enumerable
       include ::Enumerable
 
diff --git a/lib/arel/algebra/relations/row.rb b/lib/arel/algebra/relations/row.rb
new file mode 100644
index 0000000000..2d63498452
--- /dev/null
+++ b/lib/arel/algebra/relations/row.rb
@@ -0,0 +1,21 @@
+module Arel
+  class Row
+    attributes :relation, :tuple
+    deriving :==, :initialize
+    
+    def [](attribute)
+      tuple[relation.position_of(attribute)]
+    end
+    
+    def slice(*attributes)
+      Row.new(relation, attributes.inject([]) do |cheese, attribute|
+        cheese << self[attribute]
+        cheese
+      end)
+    end
+    
+    def bind(relation)
+      Row.new(relation, tuple)
+    end
+  end
+end
\ No newline at end of file
-- 
cgit v1.2.3


From 2fe585328d6a24df310d3e60059c9c7b05b64bac Mon Sep 17 00:00:00 2001
From: Nick Kallen <nkallen@nick-kallens-computer-2.local>
Date: Tue, 27 May 2008 14:19:59 -0700
Subject: performing in memory joins

---
 lib/arel/algebra/relations/row.rb | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/relations/row.rb b/lib/arel/algebra/relations/row.rb
index 2d63498452..3731dd9696 100644
--- a/lib/arel/algebra/relations/row.rb
+++ b/lib/arel/algebra/relations/row.rb
@@ -17,5 +17,9 @@ module Arel
     def bind(relation)
       Row.new(relation, tuple)
     end
+    
+    def combine(other, relation)
+      Row.new(relation, tuple + other.tuple)
+    end
   end
 end
\ No newline at end of file
-- 
cgit v1.2.3


From 20b28b441b651d0404d64049253898c061a039be Mon Sep 17 00:00:00 2001
From: Nick Kallen <nkallen@nick-kallens-computer-2.local>
Date: Tue, 27 May 2008 14:37:11 -0700
Subject: using in memory relations as results from sql relation

Conflicts:

	lib/arel/algebra/primitives/expression.rb
	lib/arel/algebra/relations/relation.rb
---
 lib/arel/algebra/extensions.rb                          |  1 +
 lib/arel/algebra/extensions/symbol.rb                   |  5 +++++
 lib/arel/algebra/primitives/attribute.rb                |  4 ++--
 lib/arel/algebra/primitives/expression.rb               |  2 +-
 lib/arel/algebra/relations/relation.rb                  | 11 +++++++++--
 lib/arel/algebra/relations/utilities/externalization.rb |  2 +-
 6 files changed, 19 insertions(+), 6 deletions(-)
 create mode 100644 lib/arel/algebra/extensions/symbol.rb

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions.rb b/lib/arel/algebra/extensions.rb
index 5338fee989..694dc60a2a 100644
--- a/lib/arel/algebra/extensions.rb
+++ b/lib/arel/algebra/extensions.rb
@@ -1,4 +1,5 @@
 require 'arel/algebra/extensions/object'
 require 'arel/algebra/extensions/class'
 require 'arel/algebra/extensions/array'
+require 'arel/algebra/extensions/symbol'
 require 'arel/algebra/extensions/hash'
diff --git a/lib/arel/algebra/extensions/symbol.rb b/lib/arel/algebra/extensions/symbol.rb
new file mode 100644
index 0000000000..787867bdc3
--- /dev/null
+++ b/lib/arel/algebra/extensions/symbol.rb
@@ -0,0 +1,5 @@
+class Symbol
+  def to_attribute(relation)
+    Arel::Attribute.new(relation, self)
+  end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/primitives/attribute.rb b/lib/arel/algebra/primitives/attribute.rb
index 7a4411e248..aa1f2ae00c 100644
--- a/lib/arel/algebra/primitives/attribute.rb
+++ b/lib/arel/algebra/primitives/attribute.rb
@@ -39,8 +39,8 @@ module Arel
         relation == new_relation ? self : Attribute.new(new_relation, name, :alias => @alias, :ancestor => self)
       end
 
-      def to_attribute
-        self
+      def to_attribute(relation)
+        bind(relation)
       end
     end
     include Transformations
diff --git a/lib/arel/algebra/primitives/expression.rb b/lib/arel/algebra/primitives/expression.rb
index 989397720c..5566e2d0b7 100644
--- a/lib/arel/algebra/primitives/expression.rb
+++ b/lib/arel/algebra/primitives/expression.rb
@@ -22,7 +22,7 @@ module Arel
         new_relation == relation ? self : self.class.new(attribute.bind(new_relation), @alias, self)
       end
 
-      def to_attribute
+      def to_attribute(relation)
         Attribute.new(relation, @alias, :ancestor => self)
       end
     end
diff --git a/lib/arel/algebra/relations/relation.rb b/lib/arel/algebra/relations/relation.rb
index fe8cab4b02..c38ab0e9c5 100644
--- a/lib/arel/algebra/relations/relation.rb
+++ b/lib/arel/algebra/relations/relation.rb
@@ -31,7 +31,7 @@ module Arel
       def join(other_relation = nil, join_class = InnerJoin)
         case other_relation
         when String
-          StringJoin.new(other_relation, self)
+          StringJoin.new(self, other_relation)
         when Relation
           JoinOperation.new(join_class, self, other_relation)
         else
@@ -85,7 +85,8 @@ module Arel
           find_attribute_matching_name(index)
         when Attribute, Expression
           find_attribute_matching_attribute(index)
-        when Array
+        when ::Array
+          # TESTME
           index.collect { |i| self[i] }
         end
       end
@@ -100,6 +101,12 @@ module Arel
         end
       end
 
+      def position_of(attribute)
+        (@position_of ||= Hash.new do |h, attribute|
+          h[attribute] = attributes.index(self[attribute])
+        end)[attribute]
+      end
+
       private
       def matching_attributes(attribute)
         (@matching_attributes ||= attributes.inject({}) do |hash, a|
diff --git a/lib/arel/algebra/relations/utilities/externalization.rb b/lib/arel/algebra/relations/utilities/externalization.rb
index bd067f2304..13758ccec9 100644
--- a/lib/arel/algebra/relations/utilities/externalization.rb
+++ b/lib/arel/algebra/relations/utilities/externalization.rb
@@ -8,7 +8,7 @@ module Arel
     end
 
     def attributes
-      @attributes ||= relation.attributes.collect(&:to_attribute).collect { |a| a.bind(self) }
+      @attributes ||= relation.attributes.collect { |a| a.to_attribute(self) }
     end
   end
 
-- 
cgit v1.2.3


From 07833d39c2885a5cddf38eeb860d79353c0f447b Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 15:47:10 -0400
Subject: basic implementation of in memory insertions

Conflicts:

	lib/arel/engines/memory/relations.rb
---
 lib/arel/algebra/relations/relation.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/relations/relation.rb b/lib/arel/algebra/relations/relation.rb
index c38ab0e9c5..9fdac26528 100644
--- a/lib/arel/algebra/relations/relation.rb
+++ b/lib/arel/algebra/relations/relation.rb
@@ -57,7 +57,7 @@ module Arel
 
       module Writable
         def insert(record)
-          session.create Insert.new(self, record); self
+          session.create Insert.new(self, record)
         end
 
         def update(assignments)
-- 
cgit v1.2.3


From 7a51983efc50c8f9092785b1b586f8884dedc01a Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 16:02:10 -0400
Subject: initial implementation of cross-engine join

Conflicts:

	lib/arel/engines/memory/relations/array.rb
	lib/arel/engines/sql/primitives.rb
---
 lib/arel/algebra/relations/row.rb | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/relations/row.rb b/lib/arel/algebra/relations/row.rb
index 3731dd9696..e8484944bd 100644
--- a/lib/arel/algebra/relations/row.rb
+++ b/lib/arel/algebra/relations/row.rb
@@ -4,12 +4,13 @@ module Arel
     deriving :==, :initialize
     
     def [](attribute)
-      tuple[relation.position_of(attribute)]
+      attribute.type_cast(tuple[relation.position_of(attribute)])
     end
     
     def slice(*attributes)
       Row.new(relation, attributes.inject([]) do |cheese, attribute|
-        cheese << self[attribute]
+        # FIXME TESTME method chaining
+        cheese << tuple[relation.relation.position_of(attribute)]
         cheese
       end)
     end
-- 
cgit v1.2.3


From 44743bed5568b3065e4f9da7972e3ea1d0d9e728 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 16:14:28 -0400
Subject: joining across engines in either direction

Conflicts:

	spec/arel/engines/memory/integration/joins/cross_engine_spec.rb
---
 lib/arel/algebra/relations/operations/join.rb | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/relations/operations/join.rb b/lib/arel/algebra/relations/operations/join.rb
index 695f360b51..02a8fa629d 100644
--- a/lib/arel/algebra/relations/operations/join.rb
+++ b/lib/arel/algebra/relations/operations/join.rb
@@ -2,7 +2,7 @@ module Arel
   class Join < Relation
     attributes :relation1, :relation2, :predicates
     deriving :==
-    delegate :engine, :name, :to => :relation1
+    delegate :name, :to => :relation1
     hash_on :relation1
 
     def initialize(relation1, relation2 = Nil.instance, *predicates)
@@ -31,6 +31,10 @@ module Arel
     def join?
       true
     end
+    
+    def engine
+      relation1.engine != relation2.engine ? Memory::Engine.new : relation1.engine
+    end
   end
 
   class InnerJoin  < Join; end
@@ -39,6 +43,10 @@ module Arel
     def attributes
       relation1.externalize.attributes
     end
+    
+    def engine
+      relation1.engine
+    end
   end
 
   class Relation
-- 
cgit v1.2.3


From dc7b51883b1cc8ad7e525b7315fb575ae77a5b3d Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 16:20:40 -0400
Subject: Whitespace

---
 lib/arel/algebra/extensions/array.rb             |  4 ++--
 lib/arel/algebra/extensions/class.rb             | 10 +++++-----
 lib/arel/algebra/extensions/hash.rb              |  2 +-
 lib/arel/algebra/extensions/pathname.rb          |  2 +-
 lib/arel/algebra/extensions/symbol.rb            |  2 +-
 lib/arel/algebra/predicates.rb                   |  2 +-
 lib/arel/algebra/primitives/attribute.rb         |  8 ++++----
 lib/arel/algebra/primitives/ordering.rb          |  8 ++++----
 lib/arel/algebra/relations.rb                    |  2 +-
 lib/arel/algebra/relations/operations/alias.rb   |  2 +-
 lib/arel/algebra/relations/operations/group.rb   |  2 +-
 lib/arel/algebra/relations/operations/join.rb    |  4 ++--
 lib/arel/algebra/relations/operations/order.rb   |  4 ++--
 lib/arel/algebra/relations/operations/skip.rb    |  4 ++--
 lib/arel/algebra/relations/operations/take.rb    |  4 ++--
 lib/arel/algebra/relations/row.rb                | 10 +++++-----
 lib/arel/algebra/relations/utilities/compound.rb |  2 +-
 lib/arel/algebra/relations/writes.rb             | 10 +++++-----
 18 files changed, 41 insertions(+), 41 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions/array.rb b/lib/arel/algebra/extensions/array.rb
index 935569a07b..48541a395e 100644
--- a/lib/arel/algebra/extensions/array.rb
+++ b/lib/arel/algebra/extensions/array.rb
@@ -2,11 +2,11 @@ class Array
   def to_hash
     Hash[*flatten]
   end
-  
+
   def group_by
     inject({}) do |groups, element|
       (groups[yield(element)] ||= []) << element
       groups
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/extensions/class.rb b/lib/arel/algebra/extensions/class.rb
index f37898e7d7..0a729d8255 100644
--- a/lib/arel/algebra/extensions/class.rb
+++ b/lib/arel/algebra/extensions/class.rb
@@ -3,11 +3,11 @@ class Class
     @attributes = attrs
     attr_reader *attrs
   end
-  
+
   def deriving(*methods)
     methods.each { |m| derive m }
   end
-  
+
   def derive(method_name)
     methods = {
       :initialize => "
@@ -24,14 +24,14 @@ class Class
     }
     class_eval methods[method_name], __FILE__, __LINE__
   end
-  
+
   def hash_on(delegatee)
     define_method :eql? do |other|
       self == other
     end
-    
+
     define_method :hash do
       @hash ||= delegatee.hash
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/extensions/hash.rb b/lib/arel/algebra/extensions/hash.rb
index 7472b5aa73..82cd5e11d3 100644
--- a/lib/arel/algebra/extensions/hash.rb
+++ b/lib/arel/algebra/extensions/hash.rb
@@ -4,4 +4,4 @@ class Hash
       bound.merge(key.bind(relation) => value.bind(relation))
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/extensions/pathname.rb b/lib/arel/algebra/extensions/pathname.rb
index 2f7e2733e7..45f1a5f6b3 100644
--- a/lib/arel/algebra/extensions/pathname.rb
+++ b/lib/arel/algebra/extensions/pathname.rb
@@ -2,4 +2,4 @@ class Pathname
   def /(path)
     (self + path).expand_path
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/extensions/symbol.rb b/lib/arel/algebra/extensions/symbol.rb
index 787867bdc3..8d324a801c 100644
--- a/lib/arel/algebra/extensions/symbol.rb
+++ b/lib/arel/algebra/extensions/symbol.rb
@@ -2,4 +2,4 @@ class Symbol
   def to_attribute(relation)
     Arel::Attribute.new(relation, self)
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/predicates.rb b/lib/arel/algebra/predicates.rb
index 7f093ded6d..72167c2b27 100644
--- a/lib/arel/algebra/predicates.rb
+++ b/lib/arel/algebra/predicates.rb
@@ -38,4 +38,4 @@ module Arel
   class LessThan              < Binary; end
   class Match                 < Binary; end
   class In                    < Binary; end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/primitives/attribute.rb b/lib/arel/algebra/primitives/attribute.rb
index aa1f2ae00c..44a2f41733 100644
--- a/lib/arel/algebra/primitives/attribute.rb
+++ b/lib/arel/algebra/primitives/attribute.rb
@@ -17,7 +17,7 @@ module Arel
     def aggregation?
       false
     end
-    
+
     def inspect
       "<Attribute #{name}>"
     end
@@ -133,16 +133,16 @@ module Arel
       end
     end
     include Expressions
-    
+
     module Orderings
       def asc
         Ascending.new(self)
       end
-      
+
       def desc
         Descending.new(self)
       end
-      
+
       alias_method :to_ordering, :asc
     end
     include Orderings
diff --git a/lib/arel/algebra/primitives/ordering.rb b/lib/arel/algebra/primitives/ordering.rb
index e8d8f97188..a60d794f27 100644
--- a/lib/arel/algebra/primitives/ordering.rb
+++ b/lib/arel/algebra/primitives/ordering.rb
@@ -3,16 +3,16 @@ module Arel
     attributes :attribute
     deriving :initialize, :==
     delegate :relation, :to => :attribute
-    
+
     def bind(relation)
       self.class.new(attribute.bind(relation))
     end
-    
+
     def to_ordering
       self
     end
   end
-  
+
   class Ascending  < Ordering; end
   class Descending < Ordering; end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/relations.rb b/lib/arel/algebra/relations.rb
index 94df5938fe..f9fa24ba25 100644
--- a/lib/arel/algebra/relations.rb
+++ b/lib/arel/algebra/relations.rb
@@ -11,4 +11,4 @@ require 'arel/algebra/relations/operations/order'
 require 'arel/algebra/relations/operations/project'
 require 'arel/algebra/relations/operations/where'
 require 'arel/algebra/relations/operations/skip'
-require 'arel/algebra/relations/operations/take'
\ No newline at end of file
+require 'arel/algebra/relations/operations/take'
diff --git a/lib/arel/algebra/relations/operations/alias.rb b/lib/arel/algebra/relations/operations/alias.rb
index 67837f6a75..0331d98b85 100644
--- a/lib/arel/algebra/relations/operations/alias.rb
+++ b/lib/arel/algebra/relations/operations/alias.rb
@@ -4,4 +4,4 @@ module Arel
     deriving :initialize
     alias_method :==, :equal?
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/relations/operations/group.rb b/lib/arel/algebra/relations/operations/group.rb
index 879f2352c5..b8975ed3d6 100644
--- a/lib/arel/algebra/relations/operations/group.rb
+++ b/lib/arel/algebra/relations/operations/group.rb
@@ -13,4 +13,4 @@ module Arel
       true
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/relations/operations/join.rb b/lib/arel/algebra/relations/operations/join.rb
index 02a8fa629d..e47d9fa9e0 100644
--- a/lib/arel/algebra/relations/operations/join.rb
+++ b/lib/arel/algebra/relations/operations/join.rb
@@ -31,7 +31,7 @@ module Arel
     def join?
       true
     end
-    
+
     def engine
       relation1.engine != relation2.engine ? Memory::Engine.new : relation1.engine
     end
@@ -43,7 +43,7 @@ module Arel
     def attributes
       relation1.externalize.attributes
     end
-    
+
     def engine
       relation1.engine
     end
diff --git a/lib/arel/algebra/relations/operations/order.rb b/lib/arel/algebra/relations/operations/order.rb
index 4e7133f5a8..a589b56997 100644
--- a/lib/arel/algebra/relations/operations/order.rb
+++ b/lib/arel/algebra/relations/operations/order.rb
@@ -2,7 +2,7 @@ module Arel
   class Order < Compound
     attributes :relation, :orderings
     deriving :==
-    
+
     def initialize(relation, *orderings, &block)
       @relation = relation
       @orderings = (orderings + arguments_from_block(relation, &block)) \
@@ -15,4 +15,4 @@ module Arel
       (orderings + relation.orders).collect { |o| o.bind(self) }.collect { |o| o.to_ordering }
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/relations/operations/skip.rb b/lib/arel/algebra/relations/operations/skip.rb
index 930e4c94ea..2dda191c35 100644
--- a/lib/arel/algebra/relations/operations/skip.rb
+++ b/lib/arel/algebra/relations/operations/skip.rb
@@ -2,9 +2,9 @@ module Arel
   class Skip < Compound
     attributes :relation, :skipped
     deriving :initialize, :==
-    
+
     def externalizable?
       true
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/relations/operations/take.rb b/lib/arel/algebra/relations/operations/take.rb
index 2fd3fdf635..eb32ec492e 100644
--- a/lib/arel/algebra/relations/operations/take.rb
+++ b/lib/arel/algebra/relations/operations/take.rb
@@ -2,9 +2,9 @@ module Arel
   class Take < Compound
     attributes :relation, :taken
     deriving :initialize, :==
-    
+
     def externalizable?
       true
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/relations/row.rb b/lib/arel/algebra/relations/row.rb
index e8484944bd..3158557448 100644
--- a/lib/arel/algebra/relations/row.rb
+++ b/lib/arel/algebra/relations/row.rb
@@ -2,11 +2,11 @@ module Arel
   class Row
     attributes :relation, :tuple
     deriving :==, :initialize
-    
+
     def [](attribute)
       attribute.type_cast(tuple[relation.position_of(attribute)])
     end
-    
+
     def slice(*attributes)
       Row.new(relation, attributes.inject([]) do |cheese, attribute|
         # FIXME TESTME method chaining
@@ -14,13 +14,13 @@ module Arel
         cheese
       end)
     end
-    
+
     def bind(relation)
       Row.new(relation, tuple)
     end
-    
+
     def combine(other, relation)
       Row.new(relation, tuple + other.tuple)
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/arel/algebra/relations/utilities/compound.rb b/lib/arel/algebra/relations/utilities/compound.rb
index 99c3d02748..676d80a737 100644
--- a/lib/arel/algebra/relations/utilities/compound.rb
+++ b/lib/arel/algebra/relations/utilities/compound.rb
@@ -13,7 +13,7 @@ module Arel
         end
       OPERATION
     end
-    
+
     private
     def arguments_from_block(relation, &block)
       block_given?? [yield(relation)] : []
diff --git a/lib/arel/algebra/relations/writes.rb b/lib/arel/algebra/relations/writes.rb
index 352f7bc7e5..d344987915 100644
--- a/lib/arel/algebra/relations/writes.rb
+++ b/lib/arel/algebra/relations/writes.rb
@@ -2,7 +2,7 @@ module Arel
   class Deletion < Compound
     attributes :relation
     deriving :initialize, :==
-    
+
     def call
       engine.delete(self)
     end
@@ -15,7 +15,7 @@ module Arel
     def initialize(relation, record)
       @relation, @record = relation, record.bind(relation)
     end
-    
+
     def call
       engine.create(self)
     end
@@ -24,13 +24,13 @@ module Arel
   class Update < Compound
     attributes :relation, :assignments
     deriving :==
-    
+
     def initialize(relation, assignments)
       @relation, @assignments = relation, assignments.bind(relation)
     end
-    
+
     def call
       engine.update(self)
     end
   end
-end
\ No newline at end of file
+end
-- 
cgit v1.2.3


From ed8e0f9c02c291a51f93a2123e099d07756d75bb Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 16:42:17 -0400
Subject: Include modules to extend core classes to improve inspectability

---
 lib/arel/algebra/extensions/array.rb    | 21 +++++++----
 lib/arel/algebra/extensions/class.rb    | 65 ++++++++++++++++++---------------
 lib/arel/algebra/extensions/hash.rb     | 12 ++++--
 lib/arel/algebra/extensions/object.rb   | 31 +++++++++-------
 lib/arel/algebra/extensions/pathname.rb | 12 ++++--
 lib/arel/algebra/extensions/symbol.rb   | 10 +++--
 6 files changed, 88 insertions(+), 63 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions/array.rb b/lib/arel/algebra/extensions/array.rb
index 48541a395e..e7e44ae909 100644
--- a/lib/arel/algebra/extensions/array.rb
+++ b/lib/arel/algebra/extensions/array.rb
@@ -1,12 +1,17 @@
-class Array
-  def to_hash
-    Hash[*flatten]
-  end
+module Arel
+  module ArrayExtensions
+    def to_hash
+      Hash[*flatten]
+    end
 
-  def group_by
-    inject({}) do |groups, element|
-      (groups[yield(element)] ||= []) << element
-      groups
+    def group_by
+      inject({}) do |groups, element|
+        (groups[yield(element)] ||= []) << element
+        groups
+      end
     end
+    
+    Array.send(:include, self)
   end
 end
+
diff --git a/lib/arel/algebra/extensions/class.rb b/lib/arel/algebra/extensions/class.rb
index 0a729d8255..d005814f91 100644
--- a/lib/arel/algebra/extensions/class.rb
+++ b/lib/arel/algebra/extensions/class.rb
@@ -1,37 +1,42 @@
-class Class
-  def attributes(*attrs)
-    @attributes = attrs
-    attr_reader *attrs
-  end
-
-  def deriving(*methods)
-    methods.each { |m| derive m }
-  end
+module Arel
+  module ClassExtensions
+    def attributes(*attrs)
+      @attributes = attrs
+      attr_reader *attrs
+    end
 
-  def derive(method_name)
-    methods = {
-      :initialize => "
-        def #{method_name}(#{@attributes.join(',')})
-          #{@attributes.collect { |a| "@#{a} = #{a}" }.join("\n")}
-        end
-      ",
-      :== => "
-        def ==(other)
-          #{name} === other &&
-          #{@attributes.collect { |a| "@#{a} == other.#{a}" }.join(" &&\n")}
-        end
-      "
-    }
-    class_eval methods[method_name], __FILE__, __LINE__
-  end
+    def deriving(*methods)
+      methods.each { |m| derive m }
+    end
 
-  def hash_on(delegatee)
-    define_method :eql? do |other|
-      self == other
+    def derive(method_name)
+      methods = {
+        :initialize => "
+          def #{method_name}(#{@attributes.join(',')})
+            #{@attributes.collect { |a| "@#{a} = #{a}" }.join("\n")}
+          end
+        ",
+        :== => "
+          def ==(other)
+            #{name} === other &&
+            #{@attributes.collect { |a| "@#{a} == other.#{a}" }.join(" &&\n")}
+          end
+        "
+      }
+      class_eval methods[method_name], __FILE__, __LINE__
     end
 
-    define_method :hash do
-      @hash ||= delegatee.hash
+    def hash_on(delegatee)
+      define_method :eql? do |other|
+        self == other
+      end
+
+      define_method :hash do
+        @hash ||= delegatee.hash
+      end
     end
+    
+    Class.send(:include, self)
   end
 end
+
diff --git a/lib/arel/algebra/extensions/hash.rb b/lib/arel/algebra/extensions/hash.rb
index 82cd5e11d3..05c15e7ebe 100644
--- a/lib/arel/algebra/extensions/hash.rb
+++ b/lib/arel/algebra/extensions/hash.rb
@@ -1,7 +1,11 @@
-class Hash
-  def bind(relation)
-    inject({}) do |bound, (key, value)|
-      bound.merge(key.bind(relation) => value.bind(relation))
+module Arel
+  module HashExtensions
+    def bind(relation)
+      inject({}) do |bound, (key, value)|
+        bound.merge(key.bind(relation) => value.bind(relation))
+      end
     end
+    
+    Hash.send(:include, self)
   end
 end
diff --git a/lib/arel/algebra/extensions/object.rb b/lib/arel/algebra/extensions/object.rb
index efdbbf525f..80d68df177 100644
--- a/lib/arel/algebra/extensions/object.rb
+++ b/lib/arel/algebra/extensions/object.rb
@@ -1,20 +1,23 @@
-class Object
-  def bind(relation)
-    Arel::Value.new(self, relation)
-  end
+module Arel
+  module ObjectExtensions
+    def bind(relation)
+      Arel::Value.new(self, relation)
+    end
 
-  def find_correlate_in(relation)
-    bind(relation)
-  end
+    def find_correlate_in(relation)
+      bind(relation)
+    end
 
-  def metaclass
-    class << self
-      self
+    def metaclass
+      class << self
+        self
+      end
     end
-  end
 
-  def let
-    yield(self)
+    def let
+      yield(self)
+    end
+    
+    Object.send(:include, self)
   end
 end
-
diff --git a/lib/arel/algebra/extensions/pathname.rb b/lib/arel/algebra/extensions/pathname.rb
index 45f1a5f6b3..829f692d79 100644
--- a/lib/arel/algebra/extensions/pathname.rb
+++ b/lib/arel/algebra/extensions/pathname.rb
@@ -1,5 +1,9 @@
-class Pathname
-  def /(path)
-    (self + path).expand_path
+module Arel
+  module PathnameExtensions
+    def /(path)
+      (self + path).expand_path
+    end
+    
+    Pathname.send(:include, self)
   end
-end
+end
\ No newline at end of file
diff --git a/lib/arel/algebra/extensions/symbol.rb b/lib/arel/algebra/extensions/symbol.rb
index 8d324a801c..9bb47ef7ab 100644
--- a/lib/arel/algebra/extensions/symbol.rb
+++ b/lib/arel/algebra/extensions/symbol.rb
@@ -1,5 +1,9 @@
-class Symbol
-  def to_attribute(relation)
-    Arel::Attribute.new(relation, self)
+module Arel
+  module SymbolExtensions
+    def to_attribute(relation)
+      Arel::Attribute.new(relation, self)
+    end
+    
+    Symbol.send(:include, self)
   end
 end
-- 
cgit v1.2.3


From 605973614add20b504489e6fac086565717db14b Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 16:48:04 -0400
Subject: Removing unused array extensions

---
 lib/arel/algebra/extensions.rb       |  1 -
 lib/arel/algebra/extensions/array.rb | 17 -----------------
 2 files changed, 18 deletions(-)
 delete mode 100644 lib/arel/algebra/extensions/array.rb

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions.rb b/lib/arel/algebra/extensions.rb
index 694dc60a2a..bc8edd3274 100644
--- a/lib/arel/algebra/extensions.rb
+++ b/lib/arel/algebra/extensions.rb
@@ -1,5 +1,4 @@
 require 'arel/algebra/extensions/object'
 require 'arel/algebra/extensions/class'
-require 'arel/algebra/extensions/array'
 require 'arel/algebra/extensions/symbol'
 require 'arel/algebra/extensions/hash'
diff --git a/lib/arel/algebra/extensions/array.rb b/lib/arel/algebra/extensions/array.rb
deleted file mode 100644
index e7e44ae909..0000000000
--- a/lib/arel/algebra/extensions/array.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module Arel
-  module ArrayExtensions
-    def to_hash
-      Hash[*flatten]
-    end
-
-    def group_by
-      inject({}) do |groups, element|
-        (groups[yield(element)] ||= []) << element
-        groups
-      end
-    end
-    
-    Array.send(:include, self)
-  end
-end
-
-- 
cgit v1.2.3


From 7fc820501ce7b997da43c47ec189aaa0d40645e1 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 16:49:15 -0400
Subject: Removing two unused externalizable? methods

---
 lib/arel/algebra/relations/operations/group.rb | 4 ----
 lib/arel/algebra/relations/operations/skip.rb  | 4 ----
 2 files changed, 8 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/relations/operations/group.rb b/lib/arel/algebra/relations/operations/group.rb
index b8975ed3d6..2bfc42214b 100644
--- a/lib/arel/algebra/relations/operations/group.rb
+++ b/lib/arel/algebra/relations/operations/group.rb
@@ -8,9 +8,5 @@ module Arel
       @groupings = (groupings + arguments_from_block(relation, &block)) \
         .collect { |g| g.bind(relation) }
     end
-
-    def externalizable?
-      true
-    end
   end
 end
diff --git a/lib/arel/algebra/relations/operations/skip.rb b/lib/arel/algebra/relations/operations/skip.rb
index 2dda191c35..689e06e1c3 100644
--- a/lib/arel/algebra/relations/operations/skip.rb
+++ b/lib/arel/algebra/relations/operations/skip.rb
@@ -2,9 +2,5 @@ module Arel
   class Skip < Compound
     attributes :relation, :skipped
     deriving :initialize, :==
-
-    def externalizable?
-      true
-    end
   end
 end
-- 
cgit v1.2.3


From 10c4b42c35f61145ac6ebb8d36f504344eef47cd Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 18:21:56 -0400
Subject: Fix bug in Order equality where Descending.new(attribute) was ==
 Ascending.new(attribute)

---
 lib/arel/algebra/primitives/ordering.rb | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/primitives/ordering.rb b/lib/arel/algebra/primitives/ordering.rb
index a60d794f27..3efb4c6280 100644
--- a/lib/arel/algebra/primitives/ordering.rb
+++ b/lib/arel/algebra/primitives/ordering.rb
@@ -1,7 +1,5 @@
 module Arel
   class Ordering
-    attributes :attribute
-    deriving :initialize, :==
     delegate :relation, :to => :attribute
 
     def bind(relation)
@@ -13,6 +11,13 @@ module Arel
     end
   end
 
-  class Ascending  < Ordering; end
-  class Descending < Ordering; end
+  class Ascending  < Ordering
+    attributes :attribute
+    deriving :initialize, :==
+  end
+  
+  class Descending < Ordering
+    attributes :attribute
+    deriving :initialize, :==
+  end
 end
-- 
cgit v1.2.3


From a842aa572af1e8fac48f8a73a2e2985fbe39e046 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Sun, 17 May 2009 18:35:45 -0400
Subject: Removing Object#metaclass definition (it's already in ActiveSupport)

---
 lib/arel/algebra/extensions/object.rb | 6 ------
 1 file changed, 6 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions/object.rb b/lib/arel/algebra/extensions/object.rb
index 80d68df177..d8c60b5dd5 100644
--- a/lib/arel/algebra/extensions/object.rb
+++ b/lib/arel/algebra/extensions/object.rb
@@ -8,12 +8,6 @@ module Arel
       bind(relation)
     end
 
-    def metaclass
-      class << self
-        self
-      end
-    end
-
     def let
       yield(self)
     end
-- 
cgit v1.2.3


From 65e419c172217f9747e2e56b36fcc4b6089a0d6d Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Mon, 18 May 2009 01:25:09 -0400
Subject: Expand usages of #hash_on. The #hash definition it produces looks
 broken, but leaving it for now

---
 lib/arel/algebra/extensions/class.rb             | 10 ----------
 lib/arel/algebra/relations/operations/join.rb    |  9 ++++++++-
 lib/arel/algebra/relations/utilities/compound.rb | 12 ++++++++++--
 3 files changed, 18 insertions(+), 13 deletions(-)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions/class.rb b/lib/arel/algebra/extensions/class.rb
index d005814f91..520111b90f 100644
--- a/lib/arel/algebra/extensions/class.rb
+++ b/lib/arel/algebra/extensions/class.rb
@@ -25,16 +25,6 @@ module Arel
       }
       class_eval methods[method_name], __FILE__, __LINE__
     end
-
-    def hash_on(delegatee)
-      define_method :eql? do |other|
-        self == other
-      end
-
-      define_method :hash do
-        @hash ||= delegatee.hash
-      end
-    end
     
     Class.send(:include, self)
   end
diff --git a/lib/arel/algebra/relations/operations/join.rb b/lib/arel/algebra/relations/operations/join.rb
index e47d9fa9e0..e9320f28e1 100644
--- a/lib/arel/algebra/relations/operations/join.rb
+++ b/lib/arel/algebra/relations/operations/join.rb
@@ -3,12 +3,19 @@ module Arel
     attributes :relation1, :relation2, :predicates
     deriving :==
     delegate :name, :to => :relation1
-    hash_on :relation1
 
     def initialize(relation1, relation2 = Nil.instance, *predicates)
       @relation1, @relation2, @predicates = relation1, relation2, predicates
     end
 
+    def hash
+      @hash ||= :relation1.hash
+    end
+
+    def eql?(other)
+      self == other
+    end
+
     def attributes
       @attributes ||= (relation1.externalize.attributes +
         relation2.externalize.attributes).collect { |a| a.bind(self) }
diff --git a/lib/arel/algebra/relations/utilities/compound.rb b/lib/arel/algebra/relations/utilities/compound.rb
index 676d80a737..5e775618f1 100644
--- a/lib/arel/algebra/relations/utilities/compound.rb
+++ b/lib/arel/algebra/relations/utilities/compound.rb
@@ -1,7 +1,6 @@
 module Arel
   class Compound < Relation
     attr_reader :relation
-    hash_on :relation
     delegate :joins, :join?, :inserts, :taken, :skipped, :name, :externalizable?,
              :column_for, :engine,
              :to => :relation
@@ -14,7 +13,16 @@ module Arel
       OPERATION
     end
 
-    private
+    def hash
+      @hash ||= :relation.hash
+    end
+
+    def eql?(other)
+      self == other
+    end
+
+  private
+
     def arguments_from_block(relation, &block)
       block_given?? [yield(relation)] : []
     end
-- 
cgit v1.2.3


From fbfbf1adcb2252c326aa869a6f94bd3269565ba2 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Mon, 18 May 2009 01:36:12 -0400
Subject: Removing unused Pathname extension

---
 lib/arel/algebra/extensions/pathname.rb | 9 ---------
 1 file changed, 9 deletions(-)
 delete mode 100644 lib/arel/algebra/extensions/pathname.rb

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/extensions/pathname.rb b/lib/arel/algebra/extensions/pathname.rb
deleted file mode 100644
index 829f692d79..0000000000
--- a/lib/arel/algebra/extensions/pathname.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module Arel
-  module PathnameExtensions
-    def /(path)
-      (self + path).expand_path
-    end
-    
-    Pathname.send(:include, self)
-  end
-end
\ No newline at end of file
-- 
cgit v1.2.3


From 082079169caab2a00f62d9de9c4bdb5dcbc591aa Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp <bryan@brynary.com>
Date: Mon, 18 May 2009 01:49:50 -0400
Subject: Better inspect output for Expressions

---
 lib/arel/algebra/primitives/expression.rb | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'lib/arel/algebra')

diff --git a/lib/arel/algebra/primitives/expression.rb b/lib/arel/algebra/primitives/expression.rb
index 5566e2d0b7..875498c282 100644
--- a/lib/arel/algebra/primitives/expression.rb
+++ b/lib/arel/algebra/primitives/expression.rb
@@ -13,6 +13,10 @@ module Arel
       true
     end
 
+    def inspect
+      "<#{self.class.name} #{attribute.inspect}>"
+    end
+
     module Transformations
       def as(aliaz)
         self.class.new(attribute, aliaz, self)
-- 
cgit v1.2.3