From 20b28b441b651d0404d64049253898c061a039be Mon Sep 17 00:00:00 2001 From: Nick Kallen 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 --- doc/TODO | 6 +++--- 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 +- lib/arel/engines/memory/relations.rb | 1 - lib/arel/engines/memory/relations/array.rb | 4 ++-- lib/arel/engines/memory/relations/relation.rb | 7 ------- lib/arel/engines/sql/engine.rb | 10 +++++----- lib/arel/engines/sql/relations/operations/join.rb | 2 +- spec/arel/algebra/unit/primitives/attribute_spec.rb | 12 ++++++++++-- spec/arel/algebra/unit/primitives/expression_spec.rb | 2 +- spec/arel/algebra/unit/relations/relation_spec.rb | 10 +++++----- 15 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 lib/arel/algebra/extensions/symbol.rb delete mode 100644 lib/arel/engines/memory/relations/relation.rb diff --git a/doc/TODO b/doc/TODO index 3f8c34f660..7e7028d39f 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,10 +1,9 @@ todo: -- result sets should be array relations -- deal with table tests in algebra +- fix AR - cross-engine joins - blocks for joins +- deal with table tests in algebra - implement mnesia adapter -- fix AR - rename externalize to derived. - fix grouping @@ -92,6 +91,7 @@ done: - reorganize memory tests - result sets to attr correlation too - implement joins in memory +- result sets should be array relations icebox: - #bind in Attribute and Expression should be doing a descend? 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 diff --git a/lib/arel/engines/memory/relations.rb b/lib/arel/engines/memory/relations.rb index 820b0af4b2..1b009537b9 100644 --- a/lib/arel/engines/memory/relations.rb +++ b/lib/arel/engines/memory/relations.rb @@ -1,4 +1,3 @@ -require 'arel/engines/memory/relations/relation' require 'arel/engines/memory/relations/array' require 'arel/engines/memory/relations/operations' require 'arel/engines/memory/relations/compound' diff --git a/lib/arel/engines/memory/relations/array.rb b/lib/arel/engines/memory/relations/array.rb index ea0b5af5ba..15a3e95e1b 100644 --- a/lib/arel/engines/memory/relations/array.rb +++ b/lib/arel/engines/memory/relations/array.rb @@ -1,8 +1,8 @@ module Arel class Array < Relation attributes :array, :attribute_names - deriving :initialize include Recursion::BaseCase + deriving :==, :initialize def engine @engine ||= Memory::Engine.new @@ -10,7 +10,7 @@ module Arel def attributes @attributes ||= @attribute_names.collect do |name| - Attribute.new(self, name.to_sym) + name.to_attribute(self) end end diff --git a/lib/arel/engines/memory/relations/relation.rb b/lib/arel/engines/memory/relations/relation.rb deleted file mode 100644 index abfb8bb37f..0000000000 --- a/lib/arel/engines/memory/relations/relation.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Arel - class Relation - def position_of(attribute) - attributes.index(self[attribute]) - end - end -end \ No newline at end of file diff --git a/lib/arel/engines/sql/engine.rb b/lib/arel/engines/sql/engine.rb index e5d1a8b0ca..0700ae9733 100644 --- a/lib/arel/engines/sql/engine.rb +++ b/lib/arel/engines/sql/engine.rb @@ -19,12 +19,12 @@ module Arel end def read(relation) - results = connection.execute(relation.to_sql) - rows = [] - results.each do |row| - rows << attributes.zip(row).to_hash + # FIXME + class << rows = connection.execute(relation.to_sql) + include Enumerable end - rows + + Array.new(rows, relation.attributes) end def update(relation) diff --git a/lib/arel/engines/sql/relations/operations/join.rb b/lib/arel/engines/sql/relations/operations/join.rb index 2f5e23644e..f848fd3268 100644 --- a/lib/arel/engines/sql/relations/operations/join.rb +++ b/lib/arel/engines/sql/relations/operations/join.rb @@ -22,7 +22,7 @@ module Arel end class OuterJoin < Join - def join_sql; "OUTER JOIN" end + def join_sql; "LEFT OUTER JOIN" end end class StringJoin < Join diff --git a/spec/arel/algebra/unit/primitives/attribute_spec.rb b/spec/arel/algebra/unit/primitives/attribute_spec.rb index bab9fad3d5..dcac5abf65 100644 --- a/spec/arel/algebra/unit/primitives/attribute_spec.rb +++ b/spec/arel/algebra/unit/primitives/attribute_spec.rb @@ -26,8 +26,16 @@ module Arel end describe '#to_attribute' do - it "returns self" do - @attribute.to_attribute.should == @attribute + describe 'when the given relation is the same as the attributes relation' do + it "returns self" do + @attribute.to_attribute(@relation).should == @attribute + end + end + + describe 'when the given relation differs from the attributes relation' do + it 'binds to the new relation' do + @attribute.to_attribute(new_relation = @relation.alias).should == @attribute.bind(new_relation) + end end end end diff --git a/spec/arel/algebra/unit/primitives/expression_spec.rb b/spec/arel/algebra/unit/primitives/expression_spec.rb index 10bdb56302..dfd2100048 100644 --- a/spec/arel/algebra/unit/primitives/expression_spec.rb +++ b/spec/arel/algebra/unit/primitives/expression_spec.rb @@ -31,7 +31,7 @@ module Arel describe '#to_attribute' do it "manufactures an attribute with the expression as an ancestor" do - @expression.to_attribute.should == Attribute.new(@expression.relation, @expression.alias, :ancestor => @expression) + @expression.to_attribute(@relation).should == Attribute.new(@relation, @expression.alias, :ancestor => @expression) end end end diff --git a/spec/arel/algebra/unit/relations/relation_spec.rb b/spec/arel/algebra/unit/relations/relation_spec.rb index 3286f373f5..9707f2887c 100644 --- a/spec/arel/algebra/unit/relations/relation_spec.rb +++ b/spec/arel/algebra/unit/relations/relation_spec.rb @@ -40,7 +40,7 @@ module Arel describe "when given a string" do it "manufactures a join operation with the string passed through" do - @relation.join(arbitrary_string = "ASDF").should == Join.new(arbitrary_string, @relation) + @relation.join(arbitrary_string = "ASDF").should == StringJoin.new(@relation, arbitrary_string) end end @@ -159,7 +159,7 @@ module Arel describe '#insert' do it 'manufactures an insertion relation' do Session.start do - record = {@relation[:name] => 'carl'} + record = { @relation[:name] => 'carl' } mock(Session.new).create(Insert.new(@relation, record)) @relation.insert(record) end @@ -169,7 +169,7 @@ module Arel describe '#update' do it 'manufactures an update relation' do Session.start do - assignments = {@relation[:name] => Value.new('bob', @relation)} + assignments = { @relation[:name] => Value.new('bob', @relation) } mock(Session.new).update(Update.new(@relation, assignments)) @relation.update(assignments) end @@ -180,8 +180,8 @@ module Arel describe Relation::Enumerable do it "implements enumerable" do - @relation.collect.should == @relation.session.read(@relation) - @relation.first.should == @relation.session.read(@relation).first + @relation.collect.should == @relation.session.read(@relation).collect + @relation.first.should == @relation.session.read(@relation).first end end end -- cgit v1.2.3