diff options
-rw-r--r-- | lib/active_relation/relations/compound.rb | 2 | ||||
-rw-r--r-- | lib/active_relation/relations/group.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/relations/join.rb | 18 | ||||
-rw-r--r-- | lib/active_relation/relations/relation.rb | 4 | ||||
-rw-r--r-- | spec/active_relation/relations/group_spec.rb | 6 | ||||
-rw-r--r-- | spec/active_relation/relations/join_spec.rb | 56 | ||||
-rw-r--r-- | spec/active_relation/relations/relation_spec.rb | 6 |
7 files changed, 76 insertions, 20 deletions
diff --git a/lib/active_relation/relations/compound.rb b/lib/active_relation/relations/compound.rb index e870f12aff..a7595c9e3d 100644 --- a/lib/active_relation/relations/compound.rb +++ b/lib/active_relation/relations/compound.rb @@ -2,7 +2,7 @@ module ActiveRelation class Compound < Relation attr_reader :relation - delegate :projections, :attribute, :joins, :selects, :orders, :groupings, :table_sql, :inserts, :limit, :offset, :name, :alias, + delegate :projections, :attribute, :joins, :selects, :orders, :groupings, :table_sql, :inserts, :limit, :offset, :name, :alias, :aggregation?, :to => :relation end end
\ No newline at end of file diff --git a/lib/active_relation/relations/group.rb b/lib/active_relation/relations/group.rb index bc363970c7..31de6f4bd8 100644 --- a/lib/active_relation/relations/group.rb +++ b/lib/active_relation/relations/group.rb @@ -13,5 +13,9 @@ module ActiveRelation def qualify Group.new(relation.qualify, *groupings.collect(&:qualify)) end + + def aggregation? + true + end end end
\ No newline at end of file diff --git a/lib/active_relation/relations/join.rb b/lib/active_relation/relations/join.rb index b624df8d72..d4cfe19239 100644 --- a/lib/active_relation/relations/join.rb +++ b/lib/active_relation/relations/join.rb @@ -26,18 +26,26 @@ module ActiveRelation relation1.send(:selects) + relation2.send(:selects) end + # this is magick!!! + def projections + relation1.send(:projections) + relation2.attributes + end + def attribute(name) relation1[name] || relation2[name] end - - protected - def projections - relation1.send(:projections) + relation2.send(:projections) - end private def join "#{join_sql} #{relation2.send(:table_sql)} ON #{predicates.collect { |p| p.to_sql(Sql::Predicate.new) }.join(' AND ')}" end + + def join + [join_sql, right_table, "ON", predicates.collect { |p| p.to_sql(Sql::Predicate.new) }.join(' AND ')].join(" ") + end + + def right_table + relation2.aggregation?? relation2.to_sql(Sql::Aggregation.new) : relation2.send(:table_sql) + end end end
\ No newline at end of file diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb index f1febc497c..cb981eb3de 100644 --- a/lib/active_relation/relations/relation.rb +++ b/lib/active_relation/relations/relation.rb @@ -80,6 +80,10 @@ module ActiveRelation def attributes projections.collect(&:to_attribute) end + + def aggregation? + false + end def to_sql(strategy = Sql::Select.new) strategy.select [ diff --git a/spec/active_relation/relations/group_spec.rb b/spec/active_relation/relations/group_spec.rb index 256d7dde45..532d6faea6 100644 --- a/spec/active_relation/relations/group_spec.rb +++ b/spec/active_relation/relations/group_spec.rb @@ -15,6 +15,12 @@ module ActiveRelation should == Group.new(@relation1.qualify, @attribute1.qualify) end end + + describe '#aggregation?' do + it "is true" do + Group.new(@relation1, @attribute1).should be_aggregation + end + end describe '#to_sql' do it "manufactures sql with an order clause" do diff --git a/spec/active_relation/relations/join_spec.rb b/spec/active_relation/relations/join_spec.rb index 68d7b83a12..00a6218c03 100644 --- a/spec/active_relation/relations/join_spec.rb +++ b/spec/active_relation/relations/join_spec.rb @@ -27,25 +27,53 @@ module ActiveRelation end describe '#attributes' do - it 'combines the attributes of the two relations' do - Join.new("INNER JOIN", @relation1, @relation2, @predicate).attributes.should == - @relation1.attributes + @relation2.attributes + describe 'with simple relations' do + it 'combines the attributes of the two relations' do + Join.new("INNER JOIN", @relation1, @relation2, @predicate).attributes.should == + @relation1.attributes + @relation2.attributes + end + end + + describe 'with aggregated relations' do + it '' do + end end end describe '#to_sql' do - before do - @relation1 = @relation1.select(@relation1[:id].equals(1)) + describe 'with simple relations' do + before do + @relation1 = @relation1.select(@relation1[:id].equals(1)) + end + + it 'manufactures sql joining the two tables on the predicate, merging the selects' do + Join.new("INNER JOIN", @relation1, @relation2, @predicate).to_sql.should be_like(""" + SELECT `foo`.`name`, `foo`.`id`, `bar`.`name`, `bar`.`foo_id`, `bar`.`id` + FROM `foo` + INNER JOIN `bar` ON `foo`.`id` = `bar`.`id` + WHERE + `foo`.`id` = 1 + """) + end end - - it 'manufactures sql joining the two tables on the predicate, merging the selects' do - Join.new("INNER JOIN", @relation1, @relation2, @predicate).to_sql.should be_like(""" - SELECT `foo`.`name`, `foo`.`id`, `bar`.`name`, `bar`.`foo_id`, `bar`.`id` - FROM `foo` - INNER JOIN `bar` ON `foo`.`id` = `bar`.`id` - WHERE - `foo`.`id` = 1 - """) + + describe 'with aggregated relations' do + before do + @relation = Table.new(:users) + photos = Table.new(:photos) + @aggregate_relation = photos.project(photos[:user_id], photos[:id].count).rename(photos[:id].count, :cnt) \ + .group(photos[:user_id]).as(:photo_count) + @predicate = Equality.new(@aggregate_relation[:user_id], @relation[:id]) + end + + it 'manufactures sql joining the left table to a derived table' do + Join.new("INNER JOIN", @relation, @aggregate_relation, @predicate).to_sql.should be_like(""" + SELECT `users`.`name`, `users`.`id`, `photo_count`.`user_id`, `photo_count`.`cnt` + FROM `users` + INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photo_count` + ON `photo_count`.`user_id` = `users`.`id` + """) + end end end end diff --git a/spec/active_relation/relations/relation_spec.rb b/spec/active_relation/relations/relation_spec.rb index 1b4ab785b7..f78f1b31b7 100644 --- a/spec/active_relation/relations/relation_spec.rb +++ b/spec/active_relation/relations/relation_spec.rb @@ -24,6 +24,12 @@ module ActiveRelation @relation1.include?(@attribute1).should be_kind_of(RelationInclusion) end end + + describe '#aggregation?' do + it "returns false" do + @relation1.should_not be_aggregation + end + end describe 'read operations' do describe 'joins' do |