diff --git a/doc/TODO b/doc/TODO index 8a8dcf53..ebc469ad 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,6 +1,13 @@ todo: - expressions should be class-based, and joins too, anything _sql should be renamed - refactor adapter pattern +- clean up block_given stuff +- reorganize sql tests +- audit unit coverage of algebra +- break out adapters into sep modules +- data objects +- remove all explicit aliasing +- blocks for joins - implement in memory adapter - implement mnesia adapter - joins become subselects in writes: @@ -11,10 +18,8 @@ users.delete().where( ) - rename externalize to derived. - and/or w/ predicates -- blocks for all operations - result sets to attr correlation too - cache expiry on write - - rewrite of arecord querycache test in light of this - transactions - scoped writes - asc/desc for orderings @@ -83,6 +88,7 @@ done: - rename select to where - rename all ion classes - joining with LIMIT is like aggregations!! +- blocks for non-joins icebox: - #bind in Attribute and Expression should be doing a descend? diff --git a/lib/arel/algebra/primitives/attribute.rb b/lib/arel/algebra/primitives/attribute.rb index 5e216770..943c5b03 100644 --- a/lib/arel/algebra/primitives/attribute.rb +++ b/lib/arel/algebra/primitives/attribute.rb @@ -109,23 +109,23 @@ def in(array) 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 b67a5e1f..98939772 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 @@ def aggregation? 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 @@ def to_attribute 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 + diff --git a/lib/arel/engines/sql/primitives.rb b/lib/arel/engines/sql/primitives.rb index 5544d637..c4968558 100644 --- a/lib/arel/engines/sql/primitives.rb +++ b/lib/arel/engines/sql/primitives.rb @@ -13,12 +13,6 @@ def to_sql(formatter = Sql::WhereCondition.new(relation)) end end - class Expression < Attribute - def to_sql(formatter = Sql::SelectClause.new(relation)) - formatter.expression self - end - end - class Value def to_sql(formatter = Sql::WhereCondition.new(relation)) formatter.value value @@ -28,4 +22,34 @@ def format(object) object.to_sql(Sql::Value.new(relation)) end end + + class Expression < Attribute + def to_sql(formatter = Sql::SelectClause.new(relation)) + formatter.expression self + end + end + + class Count < Expression + def function_sql; 'COUNT' end + end + + class Distinct < Expression + def function_sql; 'DISTINCT' end + end + + class Sum < Expression + def function_sql; 'SUM' end + end + + class Maximum < Expression + def function_sql; 'MAX' end + end + + class Minimum < Expression + def function_sql; 'MIN' end + end + + class Average < Expression + def function_sql; 'AVG' end + end end \ No newline at end of file diff --git a/spec/arel/unit/primitives/attribute_spec.rb b/spec/arel/unit/primitives/attribute_spec.rb index 6d0f146a..e512b40e 100644 --- a/spec/arel/unit/primitives/attribute_spec.rb +++ b/spec/arel/unit/primitives/attribute_spec.rb @@ -139,31 +139,31 @@ module Arel describe '#count' do it "manufactures a count Expression" do - @attribute.count.should == Expression.new(@attribute, "COUNT") + @attribute.count.should == Count.new(@attribute) end end describe '#sum' do it "manufactures a sum Expression" do - @attribute.sum.should == Expression.new(@attribute, "SUM") + @attribute.sum.should == Sum.new(@attribute) end end describe '#maximum' do it "manufactures a maximum Expression" do - @attribute.maximum.should == Expression.new(@attribute, "MAX") + @attribute.maximum.should == Maximum.new(@attribute) end end describe '#minimum' do it "manufactures a minimum Expression" do - @attribute.minimum.should == Expression.new(@attribute, "MIN") + @attribute.minimum.should == Minimum.new(@attribute) end end describe '#average' do it "manufactures an average Expression" do - @attribute.average.should == Expression.new(@attribute, "AVG") + @attribute.average.should == Average.new(@attribute) end end end diff --git a/spec/arel/unit/primitives/expression_spec.rb b/spec/arel/unit/primitives/expression_spec.rb index ebde55ff..92f300c4 100644 --- a/spec/arel/unit/primitives/expression_spec.rb +++ b/spec/arel/unit/primitives/expression_spec.rb @@ -9,13 +9,13 @@ module Arel describe Expression::Transformations do before do - @expression = Expression.new(@attribute, "COUNT") + @expression = Count.new(@attribute) end describe '#bind' do it "manufactures an attribute with a rebound relation and self as the ancestor" do derived_relation = @relation.where(@relation[:id].eq(1)) - @expression.bind(derived_relation).should == Expression.new(@attribute.bind(derived_relation), "COUNT", nil, @expression) + @expression.bind(derived_relation).should == Count.new(@attribute.bind(derived_relation), nil, @expression) end it "returns self if the substituting to the same relation" do @@ -25,7 +25,7 @@ module Arel describe '#as' do it "manufactures an aliased expression" do - @expression.as(:alias).should == Expression.new(@attribute, "COUNT", :alias, @expression) + @expression.as(:alias).should == Expression.new(@attribute, :alias, @expression) end end @@ -38,7 +38,7 @@ module Arel describe '#to_sql' do it "manufactures sql with the expression and alias" do - sql = Expression.new(@attribute, "COUNT", :alias).to_sql + sql = Count.new(@attribute, :alias).to_sql adapter_is :mysql do sql.should be_like(%Q{COUNT(`users`.`id`) AS `alias`})