aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/active_relation/relations/compound.rb2
-rw-r--r--lib/active_relation/relations/group.rb4
-rw-r--r--lib/active_relation/relations/join.rb18
-rw-r--r--lib/active_relation/relations/relation.rb4
-rw-r--r--spec/active_relation/relations/group_spec.rb6
-rw-r--r--spec/active_relation/relations/join_spec.rb56
-rw-r--r--spec/active_relation/relations/relation_spec.rb6
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