aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNick Kallen <nkallen@nick-kallens-computer-2.local>2008-02-03 22:10:38 -0800
committerNick Kallen <nkallen@nick-kallens-computer-2.local>2008-02-03 22:10:38 -0800
commitb6c0de24fadc6b9e124a36aa35718edc027130de (patch)
tree8d965b22c97102ed269e47ad5882be8e71a068d9 /lib
parent6c73e3dbc714a9752a66a6da51e7e41f372797b3 (diff)
downloadrails-b6c0de24fadc6b9e124a36aa35718edc027130de.tar.gz
rails-b6c0de24fadc6b9e124a36aa35718edc027130de.tar.bz2
rails-b6c0de24fadc6b9e124a36aa35718edc027130de.zip
this is very messy but it is finally close to feature-complete
Diffstat (limited to 'lib')
-rw-r--r--lib/active_relation/extensions/object.rb4
-rw-r--r--lib/active_relation/predicates.rb4
-rw-r--r--lib/active_relation/primitives/attribute.rb29
-rw-r--r--lib/active_relation/primitives/expression.rb50
-rw-r--r--lib/active_relation/relations/aggregation.rb11
-rw-r--r--lib/active_relation/relations/alias.rb6
-rw-r--r--lib/active_relation/relations/compound.rb12
-rw-r--r--lib/active_relation/relations/join.rb18
-rw-r--r--lib/active_relation/relations/relation.rb12
-rw-r--r--lib/active_relation/relations/rename.rb14
-rw-r--r--lib/active_relation/relations/selection.rb2
-rw-r--r--lib/active_relation/relations/table.rb12
12 files changed, 121 insertions, 53 deletions
diff --git a/lib/active_relation/extensions/object.rb b/lib/active_relation/extensions/object.rb
index 2d43120f70..1db4c845be 100644
--- a/lib/active_relation/extensions/object.rb
+++ b/lib/active_relation/extensions/object.rb
@@ -3,6 +3,10 @@ class Object
self
end
+ def substitute(relation)
+ self
+ end
+
def to_sql(strategy = ActiveRelation::Sql::Scalar.new)
strategy.scalar self
end
diff --git a/lib/active_relation/predicates.rb b/lib/active_relation/predicates.rb
index 55a6c852e2..54cc1fa5a0 100644
--- a/lib/active_relation/predicates.rb
+++ b/lib/active_relation/predicates.rb
@@ -19,6 +19,10 @@ module ActiveRelation
def qualify
self.class.new(attribute.qualify, operand.qualify)
end
+
+ def substitute(relation)
+ self.class.new(attribute.substitute(relation), operand.substitute(relation))
+ end
def to_sql(strategy = Sql::Predicate.new)
"#{attribute.to_sql(strategy)} #{predicate_sql} #{operand.to_sql(strategy)}"
diff --git a/lib/active_relation/primitives/attribute.rb b/lib/active_relation/primitives/attribute.rb
index 8d40a4141f..c17118f1e8 100644
--- a/lib/active_relation/primitives/attribute.rb
+++ b/lib/active_relation/primitives/attribute.rb
@@ -1,18 +1,18 @@
module ActiveRelation
class Attribute
- attr_reader :relation, :name, :alias
+ attr_reader :relation, :name, :alias, :ancestor
- def initialize(relation, name, aliaz = nil)
- @relation, @name, @alias = relation, name, aliaz
+ def initialize(relation, name, aliaz = nil, ancestor = nil)
+ @relation, @name, @alias, @ancestor = relation, name, aliaz, ancestor
end
module Transformations
def as(aliaz = nil)
- Attribute.new(relation, name, aliaz)
+ Attribute.new(relation, name, aliaz, self)
end
def substitute(new_relation)
- Attribute.new(new_relation, name, @alias)
+ relation == new_relation ? self : Attribute.new(new_relation, name, @alias, self)
end
def qualify
@@ -26,11 +26,19 @@ module ActiveRelation
include Transformations
def qualified_name
- "#{relation.name}.#{name}"
+ "#{prefix}.#{name}"
end
def ==(other)
- self.class == other.class and relation == other.relation and name == other.name and @alias == other.alias
+ self.class == other.class and relation == other.relation and name == other.name and @alias == other.alias and ancestor == other.ancestor
+ end
+
+ def =~(other)
+ !(history & other.history).empty?
+ end
+
+ def history
+ [self] + (ancestor ? [ancestor, ancestor.history].flatten : [])
end
module Predications
@@ -84,7 +92,12 @@ module ActiveRelation
include Expressions
def to_sql(strategy = Sql::Predicate.new)
- strategy.attribute relation.name, name, self.alias
+ strategy.attribute prefix, name, self.alias
+ end
+
+ private
+ def prefix
+ relation.prefix_for(self)
end
end
end \ No newline at end of file
diff --git a/lib/active_relation/primitives/expression.rb b/lib/active_relation/primitives/expression.rb
new file mode 100644
index 0000000000..47658c49da
--- /dev/null
+++ b/lib/active_relation/primitives/expression.rb
@@ -0,0 +1,50 @@
+module ActiveRelation
+ class Expression
+ include Sql::Quoting
+
+ attr_reader :attribute, :function_sql, :alias, :ancestor
+ delegate :relation, :to => :attribute
+
+ def initialize(attribute, function_sql, aliaz = nil, ancestor = nil)
+ @attribute, @function_sql, @alias, @ancestor = attribute, function_sql, aliaz, ancestor
+ end
+
+ module Transformations
+ def substitute(new_relation)
+ Expression.new(attribute.substitute(new_relation), function_sql, @alias, self)
+ end
+
+ def as(aliaz)
+ # key line -- note self
+ Expression.new(attribute, function_sql, aliaz, self)
+ end
+
+ def to_attribute
+ # key line -- note self
+ Attribute.new(relation, @alias, nil, self)
+ end
+ end
+ include Transformations
+
+ def to_sql(strategy = nil)
+ "#{function_sql}(#{attribute.to_sql})" + (@alias ? " AS #{quote_column_name(@alias)}" : '')
+ end
+
+ def ==(other)
+ self.class == other.class and attribute == other.attribute and function_sql == other.function_sql and ancestor == other.ancestor and @alias == other.alias
+ end
+ alias_method :eql?, :==
+
+ def hash
+ attribute.hash + function_sql.hash
+ end
+
+ def =~(other)
+ !(history & other.history).empty?
+ end
+
+ def history
+ [self] + (ancestor ? [ancestor, ancestor.history].flatten : [])
+ end
+ end
+end \ No newline at end of file
diff --git a/lib/active_relation/relations/aggregation.rb b/lib/active_relation/relations/aggregation.rb
index 161a748567..efa6ea260c 100644
--- a/lib/active_relation/relations/aggregation.rb
+++ b/lib/active_relation/relations/aggregation.rb
@@ -1,27 +1,26 @@
module ActiveRelation
class Aggregation < Compound
attr_reader :expressions, :groupings
- alias_method :attributes, :expressions
def initialize(relation, options)
@relation, @expressions, @groupings = relation, options[:expressions], options[:groupings]
end
def ==(other)
- relation == other.relation and groupings == other.groupings and expressions == other.expressions
+ self.class == other.class and relation == other.relation and groupings == other.groupings and expressions == other.expressions
end
def qualify
Aggregation.new(relation.qualify, :expressions => expressions.collect(&:qualify), :groupings => groupings.collect(&:qualify))
end
+ def attributes
+ expressions.collect { |e| e.substitute(self) }
+ end
+
protected
def aggregation?
true
end
-
- def attribute_for_expression(expression)
- expression.relation == self ? expression : (e = @expressions.detect { |e| e == expression }) && e.substitute(self)
- end
end
end \ No newline at end of file
diff --git a/lib/active_relation/relations/alias.rb b/lib/active_relation/relations/alias.rb
index 5460413b25..7b03a8c2ab 100644
--- a/lib/active_relation/relations/alias.rb
+++ b/lib/active_relation/relations/alias.rb
@@ -1,13 +1,17 @@
module ActiveRelation
class Alias < Compound
attr_reader :alias
+
+ def aliased_prefix_for(attribute)
+ @alias
+ end
def initialize(relation, aliaz)
@relation, @alias = relation, aliaz
end
def ==(other)
- relation == other.relation and @alias == other.alias
+ self.class == other.class and relation == other.relation and @alias == other.alias
end
end
end \ No newline at end of file
diff --git a/lib/active_relation/relations/compound.rb b/lib/active_relation/relations/compound.rb
index 7c4a7e707b..776620732d 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 :joins, :selects, :orders, :groupings, :table_sql, :inserts, :limit,
- :offset, :name, :alias, :aggregation?,
+ :offset, :name, :alias, :aggregation?, :prefix_for, :aliased_prefix_for,
:to => :relation
def attributes
@@ -11,15 +11,7 @@ module ActiveRelation
protected
def attribute_for_name(name)
- (a = relation[name]) && a.substitute(self)
- end
-
- def attribute_for_attribute(attribute)
- attribute.relation == self ? attribute : (a = relation[attribute]) && a.substitute(self)
- end
-
- def attribute_for_expression(expression)
- expression.relation == self ? expression : (a = relation[expression]) && a.substitute(self)
+ relation[name].substitute(self) rescue nil
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 dfc9992f0b..0327b5cd87 100644
--- a/lib/active_relation/relations/join.rb
+++ b/lib/active_relation/relations/join.rb
@@ -7,7 +7,8 @@ module ActiveRelation
end
def ==(other)
- predicates == other.predicates and
+ self.class == other.class and
+ predicates == other.predicates and
((relation1 == other.relation1 and relation2 == other.relation2) or
(relation2 == other.relation1 and relation1 == other.relation2))
end
@@ -20,8 +21,15 @@ module ActiveRelation
[
relation1.aggregation?? relation1.attributes.collect(&:to_attribute) : relation1.attributes,
relation2.aggregation?? relation2.attributes.collect(&:to_attribute) : relation2.attributes,
- ].flatten
+ ].flatten.collect { |a| a.substitute(self) }
end
+
+ def prefix_for(attribute)
+ # test me
+ (relation1[attribute] && relation1.aliased_prefix_for(attribute)) ||
+ (relation2[attribute] && relation2.aliased_prefix_for(attribute))
+ end
+ alias_method :aliased_prefix_for, :prefix_for
protected
def joins
@@ -36,11 +44,11 @@ module ActiveRelation
end
def attribute_for_name(name)
- relation1[name] || relation2[name]
+ (relation1[name] || relation2[name])
end
def attribute_for_attribute(attribute)
- relation1[attribute] || relation2[attribute]
+ (relation1[attribute] || relation2[attribute])
end
def table_sql
@@ -49,7 +57,7 @@ module ActiveRelation
private
def join
- [join_sql, right_table_sql, "ON", predicates.collect { |p| p.to_sql(Sql::Predicate.new) }.join(' AND ')].join(" ")
+ [join_sql, right_table_sql, "ON", predicates.collect { |p| p.substitute(self).to_sql(Sql::Predicate.new) }.join(' AND ')].join(" ")
end
def right_table_sql
diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb
index 838697a2ac..0f770e674c 100644
--- a/lib/active_relation/relations/relation.rb
+++ b/lib/active_relation/relations/relation.rb
@@ -30,10 +30,8 @@ module ActiveRelation
attribute_for_name(index)
when ::Range
Range.new(self, index)
- when Attribute
+ when Attribute, Expression
attribute_for_attribute(index)
- when Expression
- attribute_for_expression(index)
end
end
@@ -110,12 +108,12 @@ module ActiveRelation
ActiveRecord::Base.connection
end
- def attribute_for_attribute(attribute)
- self == attribute.relation ? attribute : nil
+ def attribute_for_name(name)
+ nil
end
- def attribute_for_expression(expression)
- nil
+ def attribute_for_attribute(attribute)
+ attributes.detect { |a| a =~ attribute }
end
def attributes; [] end
diff --git a/lib/active_relation/relations/rename.rb b/lib/active_relation/relations/rename.rb
index 8942ffbe29..8d92e9422c 100644
--- a/lib/active_relation/relations/rename.rb
+++ b/lib/active_relation/relations/rename.rb
@@ -23,22 +23,14 @@ module ActiveRelation
def attribute_for_name(name)
case
when referring_by_autonym?(name) then nil
- when referring_by_pseudonym?(name) then attribute.as(pseudonym).substitute(self)
- else (a = relation[name]) && a.substitute(self)
+ when referring_by_pseudonym?(name) then substitute(relation[attribute])
+ else relation[name].substitute(self) rescue nil
end
end
-
- def attribute_for_attribute(attribute)
- attribute.relation == self ? attribute : substitute(relation[attribute])
- end
-
- def attribute_for_expression(expression)
- expression.relation == self ? expression : substitute(relation[expression])
- end
private
def substitute(attribute)
- (relation[attribute] == relation[self.attribute] ? attribute.as(pseudonym) : attribute).substitute(self) if attribute
+ (attribute =~ self.attribute ? attribute.as(pseudonym) : attribute).substitute(self) rescue nil
end
def referring_by_autonym?(name)
diff --git a/lib/active_relation/relations/selection.rb b/lib/active_relation/relations/selection.rb
index 3ecea059d5..5f1726d381 100644
--- a/lib/active_relation/relations/selection.rb
+++ b/lib/active_relation/relations/selection.rb
@@ -8,7 +8,7 @@ module ActiveRelation
end
def ==(other)
- relation == other.relation and predicate == other.predicate
+ self.class == other.class and relation == other.relation and predicate == other.predicate
end
def qualify
diff --git a/lib/active_relation/relations/table.rb b/lib/active_relation/relations/table.rb
index ffc9077076..9e58404a51 100644
--- a/lib/active_relation/relations/table.rb
+++ b/lib/active_relation/relations/table.rb
@@ -14,15 +14,19 @@ module ActiveRelation
Rename.new self, qualifications
end
- def inspect
- "<Table: #{name}>"
+ def prefix_for(attribute)
+ name
end
-
+
+ def aliased_prefix_for(attribute)
+ name
+ end
+
protected
def attribute_for_name(name)
attributes_by_name[name.to_s]
end
-
+
def table_sql
"#{quote_table_name(name)}"
end