aboutsummaryrefslogtreecommitdiffstats
path: root/lib/arel
diff options
context:
space:
mode:
authorNick Kallen <nkallen@nick-kallens-computer-2.local>2008-05-04 16:50:03 -0700
committerNick Kallen <nkallen@nick-kallens-computer-2.local>2008-05-04 16:50:03 -0700
commitf413129f37bbbc4100317cb60179f43291e69f8e (patch)
treef640bfb9223d60f7ed46add9f157f30048b245bb /lib/arel
parent85bc3b417dc4e1ecad76fa89b5d195e2db8f5ff5 (diff)
downloadrails-f413129f37bbbc4100317cb60179f43291e69f8e.tar.gz
rails-f413129f37bbbc4100317cb60179f43291e69f8e.tar.bz2
rails-f413129f37bbbc4100317cb60179f43291e69f8e.zip
Table names seem to be disambiguated.
- Code is a mess, about to undergo some refactoring
Diffstat (limited to 'lib/arel')
-rw-r--r--lib/arel/primitives/attribute.rb13
-rw-r--r--lib/arel/primitives/value.rb4
-rw-r--r--lib/arel/relations/alias.rb12
-rw-r--r--lib/arel/relations/compound.rb4
-rw-r--r--lib/arel/relations/grouping.rb8
-rw-r--r--lib/arel/relations/join.rb42
-rw-r--r--lib/arel/relations/nil.rb1
-rw-r--r--lib/arel/relations/relation.rb37
-rw-r--r--lib/arel/relations/table.rb12
-rw-r--r--lib/arel/sql.rb49
10 files changed, 105 insertions, 77 deletions
diff --git a/lib/arel/primitives/attribute.rb b/lib/arel/primitives/attribute.rb
index 797ebfd07b..9215ea64a0 100644
--- a/lib/arel/primitives/attribute.rb
+++ b/lib/arel/primitives/attribute.rb
@@ -7,6 +7,7 @@ module Arel
@relation, @name, @alias, @ancestor = relation, name, options[:alias], options[:ancestor]
end
+ # INVESTIGATE
def alias_or_name
@alias || name
end
@@ -117,14 +118,22 @@ module Arel
end
include Expressions
- def to_sql(formatter = Sql::WhereCondition.new(engine))
- formatter.attribute relation.prefix_for(self), name, self.alias
+ def to_sql(formatter = Sql::WhereCondition.new(relation))
+ formatter.attribute self
end
def format(object)
object.to_sql(formatter)
end
+ def original_relation
+ relation.relation_for(self)
+ end
+
+ def christener
+ relation.christener
+ end
+
private
def formatter
Sql::Attribute.new(self)
diff --git a/lib/arel/primitives/value.rb b/lib/arel/primitives/value.rb
index 650557559a..5142eb45ca 100644
--- a/lib/arel/primitives/value.rb
+++ b/lib/arel/primitives/value.rb
@@ -8,12 +8,12 @@ module Arel
@value, @relation = value, relation
end
- def to_sql(formatter = Sql::WhereCondition.new(relation.engine))
+ def to_sql(formatter = Sql::WhereCondition.new(relation))
formatter.value value
end
def format(object)
- object.to_sql(Sql::Value.new(relation.engine))
+ object.to_sql(Sql::Value.new(relation))
end
def ==(other)
diff --git a/lib/arel/relations/alias.rb b/lib/arel/relations/alias.rb
index 329f94638e..b4e8965625 100644
--- a/lib/arel/relations/alias.rb
+++ b/lib/arel/relations/alias.rb
@@ -1,13 +1,19 @@
module Arel
class Alias < Compound
- attr_reader :alias
-
def initialize(relation)
@relation = relation
end
def ==(other)
- self.equal? other
+ equal? other
+ end
+
+ def table
+ self
+ end
+
+ def relation_for(attribute)
+ self[attribute] and self
end
end
end \ No newline at end of file
diff --git a/lib/arel/relations/compound.rb b/lib/arel/relations/compound.rb
index 735f586114..7367e60a2d 100644
--- a/lib/arel/relations/compound.rb
+++ b/lib/arel/relations/compound.rb
@@ -5,8 +5,8 @@ module Arel
hash_on :relation
delegate :joins, :selects, :orders, :groupings, :inserts, :taken,
- :skipped, :name, :alias, :aggregation?, :prefix_for, :column_for,
- :engine, :name_for,
+ :skipped, :name, :alias, :aggregation?, :column_for,
+ :engine, :name_for, :table, :relation_for,
:to => :relation
def attributes
diff --git a/lib/arel/relations/grouping.rb b/lib/arel/relations/grouping.rb
index 2815f62b79..e3686f7f28 100644
--- a/lib/arel/relations/grouping.rb
+++ b/lib/arel/relations/grouping.rb
@@ -15,5 +15,13 @@ module Arel
def aggregation?
true
end
+
+ def table_sql(formatter = Sql::TableReference.new(self))
+ to_sql(formatter)
+ end
+
+ def name
+ table.name + '_aggregation'
+ end
end
end \ No newline at end of file
diff --git a/lib/arel/relations/join.rb b/lib/arel/relations/join.rb
index cb24ab7717..20c19e0848 100644
--- a/lib/arel/relations/join.rb
+++ b/lib/arel/relations/join.rb
@@ -23,10 +23,6 @@ module Arel
externalize(relation2).attributes).collect { |a| a.bind(self) }
end
- def prefix_for(attribute)
- externalize(relation_for(attribute)).prefix_for(attribute)
- end
-
# TESTME: Not sure which scenario needs this method, was driven by failing tests in ActiveRecord
def column_for(attribute)
(relation1[attribute] || relation2[attribute]).column
@@ -35,7 +31,11 @@ module Arel
def joins(formatter = Sql::TableReference.new(self))
this_join = [
join_sql,
- externalize(relation2).table_sql(formatter),
+ if relation2.aggregation?
+ relation2.to_sql(formatter)
+ else
+ relation2.table.table_sql(formatter)
+ end,
("ON" unless predicates.blank?),
predicates.collect { |p| p.bind(formatter.christener).to_sql }.join(' AND ')
].compact.join(" ")
@@ -46,10 +46,6 @@ module Arel
(externalize(relation1).selects + externalize(relation2).selects).collect { |s| s.bind(self) }
end
- def table_sql(formatter = Sql::TableReference.new(self))
- externalize(relation1).table_sql(formatter)
- end
-
def name_for(relation)
@used_names ||= Hash.new(0)
@relation_names ||= Hash.new do |h, k|
@@ -59,11 +55,21 @@ module Arel
@relation_names[relation]
end
- protected
+ def table
+ relation1.aggregation?? relation1 : relation1.table
+ end
+
+ delegate :name, :to => :relation1
+
def relation_for(attribute)
- [relation1[attribute], relation2[attribute]].select { |a| a =~ attribute }.min do |a1, a2|
+ x = [relation1[attribute], relation2[attribute]].select { |a| a =~ attribute }.min do |a1, a2|
(attribute % a1).size <=> (attribute % a2).size
- end.relation.relation_for(attribute)
+ end.relation
+ if x.aggregation?
+ x
+ else
+ x.relation_for(attribute) # FIXME @demeter
+ end
end
private
@@ -74,14 +80,6 @@ module Arel
Externalizer = Struct.new(:christener, :relation) do
delegate :engine, :to => :relation
- def table_sql(formatter = Sql::TableReference.new(self))
- if relation.aggregation?
- relation.to_sql(formatter) + ' AS ' + engine.quote_table_name(formatter.name_for(relation) + (relation.aggregation?? '_aggregation' : ''))
- else
- relation.table_sql(formatter)
- end
- end
-
def selects
relation.aggregation?? [] : relation.selects
end
@@ -89,10 +87,6 @@ module Arel
def attributes
relation.aggregation?? relation.attributes.collect(&:to_attribute) : relation.attributes
end
-
- def prefix_for(attribute)
- christener.name_for(relation) + (relation.aggregation?? '_aggregation' : '')
- end
end
end
end \ No newline at end of file
diff --git a/lib/arel/relations/nil.rb b/lib/arel/relations/nil.rb
index 67eb2d3a62..258f60f478 100644
--- a/lib/arel/relations/nil.rb
+++ b/lib/arel/relations/nil.rb
@@ -1,5 +1,6 @@
module Arel
class Nil < Relation
+ def table; self end
def table_sql(formatter = nil); '' end
def name; '' end
def to_s; '' end
diff --git a/lib/arel/relations/relation.rb b/lib/arel/relations/relation.rb
index 7b414b9768..e08123eaf5 100644
--- a/lib/arel/relations/relation.rb
+++ b/lib/arel/relations/relation.rb
@@ -99,36 +99,40 @@ module Arel
def aggregation?
false
end
-
- def relation_for(attribute)
- self[attribute] and self
- end
def name_for(relation)
relation.name
end
def table_sql(formatter = Sql::TableReference.new(self))
- formatter.table name, formatter.name_for(self)
+ formatter.table self
end
end
include Externalizable
- def to_sql(formatter = Sql::SelectStatement.new(engine))
- tr = Sql::TableReference.new(self)
+ def to_sql(formatter = Sql::SelectStatement.new(self))
formatter.select [
- "SELECT #{attributes.collect { |a| a.to_sql(Sql::SelectClause.new(engine)) }.join(', ')}",
- "FROM #{table_sql(tr)}",
- (joins(tr) unless joins.blank? ),
- ("WHERE #{selects.collect { |s| s.to_sql(Sql::WhereClause.new(engine)) }.join("\n\tAND ")}" unless selects.blank? ),
- ("ORDER BY #{orders.collect { |o| o.to_sql(Sql::OrderClause.new(engine)) }.join(', ')}" unless orders.blank? ),
+ "SELECT #{attributes.collect { |a| a.to_sql(Sql::SelectClause.new(self)) }.join(', ')}",
+ "FROM #{thing}",
+ (joins(Sql::TableReference.new(self)) unless joins.blank? ),
+ ("WHERE #{selects.collect { |s| s.to_sql(Sql::WhereClause.new(self)) }.join("\n\tAND ")}" unless selects.blank? ),
+ ("ORDER BY #{orders.collect { |o| o.to_sql(Sql::OrderClause.new(self)) }.join(', ')}" unless orders.blank? ),
("GROUP BY #{groupings.collect(&:to_sql)}" unless groupings.blank? ),
("LIMIT #{taken}" unless taken.blank? ),
("OFFSET #{skipped}" unless skipped.blank? )
- ].compact.join("\n")
+ ].compact.join("\n"), name
end
alias_method :to_s, :to_sql
+ # FIXME
+ def thing
+ if table.aggregation?
+ table.to_sql(Sql::TableReference.new(self))
+ else
+ table.table_sql(Sql::TableReference.new(self))
+ end
+ end
+
def inclusion_predicate_sql
"IN"
end
@@ -159,8 +163,13 @@ module Arel
self
end
+ # INVESTIGATE
def format(object)
- object.to_sql(Sql::WhereCondition.new(engine))
+ object.to_sql(Sql::WhereCondition.new(self))
+ end
+
+ def christener
+ self
end
def attributes; [] end
diff --git a/lib/arel/relations/table.rb b/lib/arel/relations/table.rb
index 9c7d90d4fc..fcde94b595 100644
--- a/lib/arel/relations/table.rb
+++ b/lib/arel/relations/table.rb
@@ -15,14 +15,18 @@ module Arel
end
end
- def prefix_for(attribute)
- self[attribute] and name
- end
-
def column_for(attribute)
self[attribute] and columns.detect { |c| c.name == attribute.name.to_s }
end
+ def table
+ self
+ end
+
+ def relation_for(attribute)
+ self[attribute] and self
+ end
+
def ==(other)
self.class == other.class and
name == other.name
diff --git a/lib/arel/sql.rb b/lib/arel/sql.rb
index 7a620009db..de0bece372 100644
--- a/lib/arel/sql.rb
+++ b/lib/arel/sql.rb
@@ -5,22 +5,23 @@ module Arel
end
class Formatter
- attr_reader :engine
+ attr_reader :engine, :christener
include Quoting
- def initialize(engine)
- @engine = engine
+ def initialize(environment)
+ @christener, @engine = environment.christener, environment.engine
end
end
class SelectClause < Formatter
- def attribute(relation_name, attribute_name, aliaz)
- "#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}" + (aliaz ? " AS #{quote(aliaz.to_s)}" : "")
+ def attribute(attribute)
+ relation_name = @christener.name_for(attribute.original_relation)
+ "#{quote_table_name(relation_name)}.#{quote_column_name(attribute.name)}" + (attribute.alias ? " AS #{quote(attribute.alias.to_s)}" : "")
end
- def select(select_sql)
- "(#{select_sql})"
+ def select(select_sql, name)
+ "(#{select_sql}) AS #{quote_table_name(name.to_s)}"
end
def value(value)
@@ -37,15 +38,17 @@ module Arel
class WhereClause < PassThrough
end
- class OrderClause < PassThrough
- def attribute(relation_name, attribute_name, aliaz)
- "#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}"
+ class OrderClause < PassThrough
+ def attribute(attribute)
+ relation_name = @christener.name_for(attribute.original_relation)
+ "#{quote_table_name(relation_name)}.#{quote_column_name(attribute.name)}"
end
end
class WhereCondition < Formatter
- def attribute(relation_name, attribute_name, aliaz)
- "#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}"
+ def attribute(attribute)
+ relation_name = @christener.name_for(attribute.original_relation)
+ "#{quote_table_name(relation_name)}.#{quote_column_name(attribute.name)}"
end
def value(value)
@@ -56,37 +59,31 @@ module Arel
quote(value, column)
end
- def select(select_sql)
+ def select(select_sql, name)
"(#{select_sql})"
end
end
class SelectStatement < Formatter
- def select(select_sql)
+ def select(select_sql, name)
select_sql
end
end
class TableReference < Formatter
- attr_reader :christener
- delegate :name_for, :to => :@christener
-
- def initialize(christener)
- @christener, @engine = christener, christener.engine
- end
-
- def select(select_sql)
- "(#{select_sql})"
+ def select(select_sql, name)
+ "(#{select_sql}) AS #{quote_table_name(name)}"
end
- def table(name, aliaz)
- quote_table_name(name) + (name != aliaz ? " AS " + engine.quote_table_name(aliaz) : '')
+ def table(table)
+ aliaz = christener.name_for(table)
+ quote_table_name(table.name) + (table.name != aliaz ? " AS " + engine.quote_table_name(aliaz) : '')
end
end
class Attribute < WhereCondition
def initialize(attribute)
- @attribute, @engine = attribute, attribute.engine
+ @attribute, @christener, @engine = attribute, attribute.christener, attribute.engine
end
def scalar(scalar)