From d62ace142ce873c72eb916f5a14aa33a67ecfb86 Mon Sep 17 00:00:00 2001 From: Nick Kallen Date: Mon, 21 Jan 2008 18:22:55 -0800 Subject: completed initial functionality for joining with aggregation (the meaning of which is joining on a subselect/derived table); the big change is the introduction of a #projections protected method; this is a private version of #attributes which preserves implementation information (e.g., the name of the function called) --- .../active_relation/primitives/aggregation_spec.rb | 38 +++++++++++++++--- spec/active_relation/primitives/attribute_spec.rb | 45 ++++++++++++++-------- spec/active_relation/relations/alias_spec.rb | 9 ----- spec/active_relation/relations/join_spec.rb | 7 ++++ spec/active_relation/relations/rename_spec.rb | 6 --- spec/active_relation/relations/schmoin_spec.rb | 8 ++-- spec/spec_helper.rb | 1 + 7 files changed, 74 insertions(+), 40 deletions(-) (limited to 'spec') diff --git a/spec/active_relation/primitives/aggregation_spec.rb b/spec/active_relation/primitives/aggregation_spec.rb index fbd846ffed..5daf774e06 100644 --- a/spec/active_relation/primitives/aggregation_spec.rb +++ b/spec/active_relation/primitives/aggregation_spec.rb @@ -16,19 +16,47 @@ module ActiveRelation end end - describe '#substitute' do - it "distributes over the attribute" do - Aggregation.new(@relation1[:id], "SUM").substitute(@relation2). \ - should == Aggregation.new(@relation1[:id].substitute(@relation2), "SUM") + describe Aggregation::Transformations do + describe '#substitute' do + it "distributes over the attribute and alias" do + Aggregation.new(@relation1[:id], "SUM", "alias").substitute(@relation2). \ + should == Aggregation.new(@relation1[:id].substitute(@relation2), "SUM", "alias") + end + end + + describe '#as' do + it "manufactures an aliased aggregation" do + Aggregation.new(@relation1[:id], "SUM").as(:doof). \ + should == Aggregation.new(@relation1[:id], "SUM", :doof) + end + end + + describe '#to_attribute' do + it "manufactures an attribute the name of which corresponds to the aggregation's alias" do + Aggregation.new(@relation1[:id], "SUM", :schmaggregation).to_attribute. \ + should == Attribute.new(@relation1, :schmaggregation) + end + end + end + + describe '#relation' do + it "delegates to the attribute" do + Aggregation.new(@relation1[:id], "SUM").relation.should == @relation1 end end describe '#to_sql' do it 'manufactures sql with an aggregation function' do - @relation1[:id].maximum.to_sql.should be_like(""" + Aggregation.new(@relation1[:id], "MAX").to_sql.should be_like(""" MAX(`foo`.`id`) """) end + + it 'manufactures sql with an aliased aggregation function' do + Aggregation.new(@relation1[:id], "MAX", "marx").to_sql.should be_like(""" + MAX(`foo`.`id`) AS `marx` + """) + end end end end \ No newline at end of file diff --git a/spec/active_relation/primitives/attribute_spec.rb b/spec/active_relation/primitives/attribute_spec.rb index 543217b9cf..7f5d4922b8 100644 --- a/spec/active_relation/primitives/attribute_spec.rb +++ b/spec/active_relation/primitives/attribute_spec.rb @@ -7,31 +7,43 @@ module ActiveRelation @relation2 = Table.new(:bar) end - describe '#as' do - it "manufactures an aliased attributed when provided a parameter" do - @relation1[:id].as(:alias).should == Attribute.new(@relation1, :id, :alias) + describe Attribute::Transformations do + before do + @attribute = Attribute.new(@relation1, :id) + end + + describe '#as' do + it "manufactures an aliased attributed" do + @attribute.as(:alias).should == Attribute.new(@relation1, @attribute.name, :alias) + end end - end - describe '#substitute' do - it "manufactures an attribute with the relation substituted" do - @relation1[:id].substitute(@relation2).should == Attribute.new(@relation2, :id) + describe '#substitute' do + it "manufactures an attribute with the relation substituted" do + @attribute.substitute(@relation2).should == Attribute.new(@relation2, @attribute.name) + end + end + + describe '#qualify' do + it "manufactures an attribute aliased with that attributes qualified name" do + @attribute.qualify.should == Attribute.new(@attribute.relation, @attribute.name, @attribute.qualified_name) + end + end + + describe '#to_attribute' do + it "returns self" do + @attribute.to_attribute.should == @attribute + end end end - + describe '#qualified_name' do it "manufactures an attribute name prefixed with the relation's name" do - @relation1[:id].qualified_name.should == 'foo.id' + Attribute.new(@relation1, :id).qualified_name.should == 'foo.id' end it "manufactures an attribute name prefixed with the relation's aliased name" do - @relation1.as(:bar)[:id].qualified_name.should == 'bar.id' - end - end - - describe '#qualify' do - it "manufactures an attribute aliased with that attributes qualified name" do - @relation1[:id].qualify.should == @relation1[:id].qualify + Attribute.new(@relation1.as(:bar), :id).qualified_name.should == 'bar.id' end end @@ -40,6 +52,7 @@ module ActiveRelation Attribute.new(@relation1, :name).should == Attribute.new(@relation1, :name) Attribute.new(@relation1, :name).should_not == Attribute.new(@relation1, :another_name) Attribute.new(@relation1, :name).should_not == Attribute.new(@relation2, :name) + Attribute.new(@relation1, :name).should_not == Aggregation.new(Attribute.new(@relation1, :name), "SUM") end end diff --git a/spec/active_relation/relations/alias_spec.rb b/spec/active_relation/relations/alias_spec.rb index 418af7fe66..6c203990eb 100644 --- a/spec/active_relation/relations/alias_spec.rb +++ b/spec/active_relation/relations/alias_spec.rb @@ -25,14 +25,5 @@ module ActiveRelation @alias_relation[:does_not_exist].should be_nil end end - - describe '#to_sql' do - it "manufactures an aliased select query" do - @alias_relation.to_sql.should be_like(""" - SELECT `foo`.`name`, `foo`.`id` - FROM `users` AS `foo` - """) - end - end end end \ No newline at end of file diff --git a/spec/active_relation/relations/join_spec.rb b/spec/active_relation/relations/join_spec.rb index 25c505e371..68d7b83a12 100644 --- a/spec/active_relation/relations/join_spec.rb +++ b/spec/active_relation/relations/join_spec.rb @@ -25,6 +25,13 @@ module ActiveRelation should == Join.new("INNER JOIN", @relation1.qualify, @relation2.qualify, @predicate.qualify) end 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 + end + end describe '#to_sql' do before do diff --git a/spec/active_relation/relations/rename_spec.rb b/spec/active_relation/relations/rename_spec.rb index 3f8d5e3dbd..eb0e1f48dd 100644 --- a/spec/active_relation/relations/rename_spec.rb +++ b/spec/active_relation/relations/rename_spec.rb @@ -38,12 +38,6 @@ module ActiveRelation end end - describe '#schmattribute' do - it "should be renamed" do - pending - end - end - describe '#qualify' do it "distributes over the relation and renames" do Rename.new(@relation, @relation[:id] => :schmid).qualify. \ diff --git a/spec/active_relation/relations/schmoin_spec.rb b/spec/active_relation/relations/schmoin_spec.rb index 14e583afab..e5ed9be393 100644 --- a/spec/active_relation/relations/schmoin_spec.rb +++ b/spec/active_relation/relations/schmoin_spec.rb @@ -5,17 +5,17 @@ module ActiveRelation before do @relation = Table.new(:users) photos = Table.new(:photos) - @aggregate_relation = photos.project(photos[:user_id], photos[:id].count).group(photos[:user_id]).as(:photo_count) + @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 describe '#to_sql' do it 'manufactures sql joining the two tables on the predicate, merging the selects' do - pending Schmoin.new("INNER JOIN", @relation, @aggregate_relation, @predicate).to_sql.should be_like(""" - SELECT `users`.`name` + SELECT `users`.`name`, `users`.`id`, `photo_count`.`user_id`, `photo_count`.`cnt` FROM `users` - INNER JOIN (SELECT `photos`.`user_id`, count(`photos`.`id`) FROM `photos`) AS `photo_count` + 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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8f5d76370c..e3508aac90 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ require 'rubygems' require 'spec' +require 'pp' dir = File.dirname(__FILE__) $LOAD_PATH.unshift "#{dir}/../lib" Dir["#{dir}/matchers/*"].each { |m| require "#{dir}/matchers/#{File.basename(m)}" } -- cgit v1.2.3