From 4466409205d697f854f98ac0908a792a1601ecc6 Mon Sep 17 00:00:00 2001 From: Nick Kallen Date: Sun, 13 Apr 2008 17:03:03 -0700 Subject: adjacency lists work - implementation is a bit complex, but i can't think of anything simpler --- doc/TODO | 23 ++++++++++------------ lib/active_relation/primitives/attribute.rb | 8 ++++++++ lib/active_relation/relations/join.rb | 22 ++++++++++++++++++--- .../unit/primitives/attribute_spec.rb | 1 + spec/active_relation/unit/relations/join_spec.rb | 3 +-- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/doc/TODO b/doc/TODO index 878e240a4f..16cbc0d77a 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,20 +1,11 @@ todo: - rename ActiveRelation to arel -- investigate linq vocabularity -- test blank checks in relation.rb +- incorporate linq vocabularity - mock out database -- standardize quoting - - use strings everywhere, not symbols ? -- "unit" test sql strategies - - use real world examples, so they should be like a tutorial. -- investigage complex joining cases: - - aggregations - - left outer joins - - adjacency lists - +- fix complex joining cases: +- extract adapters - cache expiry on write - - rewrite of querycache test in light of this -- rename the tion (Selection) classes so that words that don't end in tion don't seem inconsistent + - rewrite of arecord querycache test in light of this done: . Relation <=> Relation -> InnerJoinOperation @@ -65,7 +56,13 @@ done: - finish pending tests - test relation, table reset - test Value, in particular bind. +- test blank checks in relation.rb icebox: - #bind in Attribute and Expression should be doing a descend? - try to make aggegration testing in join spec to be a bit more unit-like +- standardize quoting + - use strings everywhere, not symbols ? +- "unit" test sql strategies + - use real world examples, so they should be like a tutorial. +- rename the tion (Selection) classes so that words that don't end in tion don't seem inconsistent diff --git a/lib/active_relation/primitives/attribute.rb b/lib/active_relation/primitives/attribute.rb index d815656794..d37271490a 100644 --- a/lib/active_relation/primitives/attribute.rb +++ b/lib/active_relation/primitives/attribute.rb @@ -54,6 +54,14 @@ module ActiveRelation def =~(other) !(history & other.history).empty? end + + def %(other) + if other + (history - other.history) + (other.history - history) + else + history + end + end end include Congruence diff --git a/lib/active_relation/relations/join.rb b/lib/active_relation/relations/join.rb index dbcb520b92..a3e45f7f81 100644 --- a/lib/active_relation/relations/join.rb +++ b/lib/active_relation/relations/join.rb @@ -24,8 +24,17 @@ module ActiveRelation end def prefix_for(attribute) - externalize(relation1).prefix_for(attribute) or - externalize(relation2).prefix_for(attribute) + if relation1[attribute] && !relation2[attribute] + externalize(relation1).prefix_for(attribute) + elsif relation2[attribute] && !relation1[attribute] + externalize(relation2).prefix_for(attribute) + else + if (attribute % relation1[attribute]).size < (attribute % relation2[attribute]).size + externalize(relation1).prefix_for(attribute) + else + externalize(relation2).prefix_for(attribute) + end + end end def joins @@ -55,7 +64,14 @@ module ActiveRelation delegate :engine, :to => :relation def table_sql - relation.aggregation?? relation.to_sql(Sql::TableReference.new(engine)) : relation.table_sql + case + when relation.aggregation? + relation.to_sql(Sql::TableReference.new(engine)) + when relation.alias? + relation.table_sql + ' AS ' + engine.quote_table_name(relation.alias.to_s) + else + relation.table_sql + end end def selects diff --git a/spec/active_relation/unit/primitives/attribute_spec.rb b/spec/active_relation/unit/primitives/attribute_spec.rb index 08ed6d3621..471ae91b5b 100644 --- a/spec/active_relation/unit/primitives/attribute_spec.rb +++ b/spec/active_relation/unit/primitives/attribute_spec.rb @@ -52,6 +52,7 @@ module ActiveRelation describe Attribute::Congruence do describe '=~' do + it "obtains if the attributes are identical" do Attribute.new(@relation, :name).should =~ Attribute.new(@relation, :name) end diff --git a/spec/active_relation/unit/relations/join_spec.rb b/spec/active_relation/unit/relations/join_spec.rb index 5d554cd9ab..22b0a9f237 100644 --- a/spec/active_relation/unit/relations/join_spec.rb +++ b/spec/active_relation/unit/relations/join_spec.rb @@ -146,12 +146,11 @@ module ActiveRelation describe 'when joining aliased relations' do it 'aliases the table and attributes properly' do - pending aliased_relation = @relation1.as(:alias) @relation1.join(aliased_relation).on(@relation1[:id].eq(aliased_relation[:id])).to_sql.should be_like(" SELECT `users`.`id`, `users`.`name`, `alias`.`id`, `alias`.`name` FROM `users` - INNER JOIN `alias` + INNER JOIN `users` AS `alias` ON `users`.`id` = `alias`.`id` ") end -- cgit v1.2.3