diff options
author | Josh Susser <josh@hasmanythrough.com> | 2008-03-15 18:13:46 -0700 |
---|---|---|
committer | Josh Susser <josh@hasmanythrough.com> | 2008-03-15 18:13:46 -0700 |
commit | 9c00e8b0f0dc422e4bf5efa3fb79cda2cb0ac6a1 (patch) | |
tree | a5ce787629563b0265be9d35c1adf3a9504a4012 /lib/active_relation | |
parent | 5d7c8176f1df8df819dadb1973a202a1c2d9836d (diff) | |
parent | cd9efb9eec6198f08b4fd5d754a33aa1b1669b37 (diff) | |
download | rails-9c00e8b0f0dc422e4bf5efa3fb79cda2cb0ac6a1.tar.gz rails-9c00e8b0f0dc422e4bf5efa3fb79cda2cb0ac6a1.tar.bz2 rails-9c00e8b0f0dc422e4bf5efa3fb79cda2cb0ac6a1.zip |
merge changes from nick
Diffstat (limited to 'lib/active_relation')
20 files changed, 108 insertions, 62 deletions
diff --git a/lib/active_relation/.DS_Store b/lib/active_relation/.DS_Store Binary files differindex 2a449ff62e..9918127870 100644 --- a/lib/active_relation/.DS_Store +++ b/lib/active_relation/.DS_Store diff --git a/lib/active_relation/extensions.rb b/lib/active_relation/extensions.rb index 8a024947ed..7268a5549b 100644 --- a/lib/active_relation/extensions.rb +++ b/lib/active_relation/extensions.rb @@ -1,3 +1,4 @@ require 'active_relation/extensions/object' +require 'active_relation/extensions/class' require 'active_relation/extensions/array' require 'active_relation/extensions/hash' diff --git a/lib/active_relation/extensions/array.rb b/lib/active_relation/extensions/array.rb index aa4354a78a..4bd20d8121 100644 --- a/lib/active_relation/extensions/array.rb +++ b/lib/active_relation/extensions/array.rb @@ -2,7 +2,7 @@ class Array def to_hash Hash[*flatten] end - + def to_sql(strategy = nil) "(#{collect(&:to_sql).join(', ')})" end diff --git a/lib/active_relation/extensions/class.rb b/lib/active_relation/extensions/class.rb new file mode 100644 index 0000000000..0e5b728c26 --- /dev/null +++ b/lib/active_relation/extensions/class.rb @@ -0,0 +1,17 @@ +class Class + def abstract(*methods) + methods.each do |method| + define_method method do + raise NotImplementedError + end + end + end + + def hash_on(delegatee) + define_method :eql? do |other| + self == other + end + + delegate :hash, :to => delegatee + end +end
\ No newline at end of file diff --git a/lib/active_relation/extensions/object.rb b/lib/active_relation/extensions/object.rb index d13cf9aabb..90eb73f0b0 100644 --- a/lib/active_relation/extensions/object.rb +++ b/lib/active_relation/extensions/object.rb @@ -1,6 +1,6 @@ class Object def bind(relation) - ActiveRelation::Scalar.new(self, relation) + ActiveRelation::Value.new(self, relation) end def metaclass diff --git a/lib/active_relation/predicates.rb b/lib/active_relation/predicates.rb index ba926a86e5..12ddd1b48d 100644 --- a/lib/active_relation/predicates.rb +++ b/lib/active_relation/predicates.rb @@ -25,7 +25,7 @@ module ActiveRelation end def to_sql(strategy = nil) - "#{operand1.to_sql(operand2.strategy)} #{predicate_sql} #{operand2.to_sql(operand1.strategy)}" + "#{operand2.format(operand1)} #{predicate_sql} #{operand1.format(operand2)}" end def descend diff --git a/lib/active_relation/primitives.rb b/lib/active_relation/primitives.rb index 7629256034..9909734d24 100644 --- a/lib/active_relation/primitives.rb +++ b/lib/active_relation/primitives.rb @@ -1,4 +1,4 @@ require 'active_relation/primitives/attribute' -require 'active_relation/primitives/scalar' +require 'active_relation/primitives/value' require 'active_relation/primitives/expression' diff --git a/lib/active_relation/primitives/attribute.rb b/lib/active_relation/primitives/attribute.rb index baaae1973c..0fed676727 100644 --- a/lib/active_relation/primitives/attribute.rb +++ b/lib/active_relation/primitives/attribute.rb @@ -48,10 +48,7 @@ module ActiveRelation module Congruence def self.included(klass) - klass.class_eval do - alias_method :eql?, :== - delegate :hash, :to => :name - end + klass.hash_on :name end def history @@ -114,15 +111,19 @@ module ActiveRelation end include Expressions - def to_sql(strategy = self.strategy) + def to_sql(strategy = Sql::WhereCondition.new(engine)) strategy.attribute prefix, name, self.alias end + def format(object) + object.to_sql(strategy) + end + + private def strategy Sql::Attribute.new(self) end - private def prefix relation.prefix_for(self) end diff --git a/lib/active_relation/primitives/scalar.rb b/lib/active_relation/primitives/value.rb index fa88404ee3..096c876ecd 100644 --- a/lib/active_relation/primitives/scalar.rb +++ b/lib/active_relation/primitives/value.rb @@ -1,17 +1,17 @@ module ActiveRelation - class Scalar + class Value attr_reader :value, :relation def initialize(value, relation) @value, @relation = value, relation end - def to_sql(strategy = self.strategy) - strategy.scalar value + def to_sql(strategy = Sql::WhereCondition.new(relation.engine)) + strategy.value value end - def strategy - ActiveRelation::Sql::Scalar.new(relation.engine) + def format(object) + object.to_sql(Sql::Value.new(relation.engine)) end def ==(other) diff --git a/lib/active_relation/relations.rb b/lib/active_relation/relations.rb index f992fca8be..7776fd3d18 100644 --- a/lib/active_relation/relations.rb +++ b/lib/active_relation/relations.rb @@ -1,5 +1,6 @@ require 'active_relation/relations/relation' require 'active_relation/relations/compound' +require 'active_relation/relations/writing' require 'active_relation/relations/table' require 'active_relation/relations/join' require 'active_relation/relations/aggregation' diff --git a/lib/active_relation/relations/compound.rb b/lib/active_relation/relations/compound.rb index a10b7588e7..fac0939c6f 100644 --- a/lib/active_relation/relations/compound.rb +++ b/lib/active_relation/relations/compound.rb @@ -1,5 +1,7 @@ module ActiveRelation class Compound < Relation + abstract :==, :descend + attr_reader :relation delegate :joins, :selects, :orders, :groupings, :table_sql, :inserts, :limit, :offset, :name, :alias, :aggregation?, :alias?, :prefix_for, :column_for, diff --git a/lib/active_relation/relations/deletion.rb b/lib/active_relation/relations/deletion.rb index f3d81baf27..0fcf523efe 100644 --- a/lib/active_relation/relations/deletion.rb +++ b/lib/active_relation/relations/deletion.rb @@ -1,5 +1,5 @@ module ActiveRelation - class Deletion < Compound + class Deletion < Writing def initialize(relation) @relation = relation end @@ -12,6 +12,10 @@ module ActiveRelation ].compact.join("\n") end + def call(connection = engine.connection) + connection.delete(to_sql) + end + def ==(other) self.class == other.class and relation == other.relation diff --git a/lib/active_relation/relations/insertion.rb b/lib/active_relation/relations/insertion.rb index 16fe3d5f46..ce065b64c1 100644 --- a/lib/active_relation/relations/insertion.rb +++ b/lib/active_relation/relations/insertion.rb @@ -1,5 +1,5 @@ module ActiveRelation - class Insertion < Compound + class Insertion < Writing attr_reader :record def initialize(relation, record) @@ -15,6 +15,10 @@ module ActiveRelation ].join("\n") end + def call(connection = engine.connection) + connection.insert(to_sql) + end + def ==(other) self.class == other.class and relation == other.relation and diff --git a/lib/active_relation/relations/join.rb b/lib/active_relation/relations/join.rb index 043b237de7..4a57795280 100644 --- a/lib/active_relation/relations/join.rb +++ b/lib/active_relation/relations/join.rb @@ -61,7 +61,7 @@ module ActiveRelation delegate :engine, :to => :relation def table_sql - relation.aggregation?? relation.to_sql(Sql::Aggregation.new(engine)) : relation.send(:table_sql) + relation.aggregation?? relation.to_sql(Sql::TableReference.new(engine)) : relation.send(:table_sql) end def selects diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb index 1c97cc7035..15782cde06 100644 --- a/lib/active_relation/relations/relation.rb +++ b/lib/active_relation/relations/relation.rb @@ -1,5 +1,7 @@ module ActiveRelation class Relation + abstract :attributes, :selects, :orders, :inserts, :groupings, :joins, :limit, :offset, :alias + def session Session.new end @@ -102,38 +104,41 @@ module ActiveRelation false end - def eql?(other) - self == other - end - - def to_sql(strategy = Sql::Relation.new(engine)) + def to_sql(strategy = Sql::SelectStatement.new(engine)) strategy.select [ - "SELECT #{attributes.collect{ |a| a.to_sql(Sql::Projection.new(engine)) }.join(', ')}", + "SELECT #{attributes.collect{ |a| a.to_sql(Sql::SelectExpression.new(engine)) }.join(', ')}", "FROM #{table_sql}", - (joins unless joins.blank? ), - ("WHERE #{selects.collect{|s| s.to_sql(Sql::Selection.new(engine))}.join("\n\tAND ")}" unless selects.blank? ), - ("ORDER BY #{orders.collect(&:to_sql)}" unless orders.blank? ), - ("GROUP BY #{groupings.collect(&:to_sql)}" unless groupings.blank? ), - ("LIMIT #{limit}" unless limit.blank? ), - ("OFFSET #{offset}" unless offset.blank? ) + (joins unless joins.blank? ), + ("WHERE #{selects.collect{|s| s.to_sql(Sql::WhereClause.new(engine))}.join("\n\tAND ")}" unless selects.blank? ), + ("ORDER BY #{orders.collect(&:to_sql)}" unless orders.blank? ), + ("GROUP BY #{groupings.collect(&:to_sql)}" unless groupings.blank? ), + ("LIMIT #{limit}" unless limit.blank? ), + ("OFFSET #{offset}" unless offset.blank? ) ].compact.join("\n"), self.alias end alias_method :to_s, :to_sql - - def attribute_for_name(name) - attributes.detect { |a| a.alias_or_name.to_s == name.to_s } + + def call(connection = engine.connection) + connection.select_all(to_sql) end + + module AttributeAccessors + def attribute_for_name(name) + attributes.detect { |a| a.alias_or_name.to_s == name.to_s } + end - def attribute_for_attribute(attribute) - attributes.detect { |a| a =~ attribute } + def attribute_for_attribute(attribute) + attributes.detect { |a| a =~ attribute } + end end + include AttributeAccessors def bind(relation) self end - def strategy - Sql::Predicate.new(engine) + def format(object) + object.to_sql(Sql::WhereCondition.new(engine)) end def attributes; [] end diff --git a/lib/active_relation/relations/table.rb b/lib/active_relation/relations/table.rb index 84eb1213ee..4682298608 100644 --- a/lib/active_relation/relations/table.rb +++ b/lib/active_relation/relations/table.rb @@ -3,7 +3,7 @@ module ActiveRelation cattr_accessor :engine attr_reader :name, :engine - delegate :hash, :to => :name + hash_on :name def initialize(name, engine = Table.engine) @name, @engine = name.to_s, engine diff --git a/lib/active_relation/relations/update.rb b/lib/active_relation/relations/update.rb index c50919af3e..a51f248866 100644 --- a/lib/active_relation/relations/update.rb +++ b/lib/active_relation/relations/update.rb @@ -1,5 +1,5 @@ module ActiveRelation - class Update < Compound + class Update < Writing attr_reader :assignments def initialize(relation, assignments) @@ -16,6 +16,10 @@ module ActiveRelation ].join("\n") end + def call(connection = engine.connection) + connection.update(to_sql) + end + def ==(other) self.class == other.class and relation == other.relation and diff --git a/lib/active_relation/relations/writing.rb b/lib/active_relation/relations/writing.rb new file mode 100644 index 0000000000..3054e9b72f --- /dev/null +++ b/lib/active_relation/relations/writing.rb @@ -0,0 +1,5 @@ +module ActiveRelation + class Writing < Compound + abstract :call, :to_sql + end +end
\ No newline at end of file diff --git a/lib/active_relation/sessions/session.rb b/lib/active_relation/sessions/session.rb index 4bdbe69978..fe917a0e4d 100644 --- a/lib/active_relation/sessions/session.rb +++ b/lib/active_relation/sessions/session.rb @@ -25,22 +25,22 @@ module ActiveRelation module CRUD def create(insert) - insert.engine.insert(insert.to_sql) + insert.call(insert.engine.connection) end def read(select) @read ||= Hash.new do |hash, select| - hash[select] = select.engine.select_all(select.to_sql) + hash[select] = select.call(select.engine.connection) end @read[select] end def update(update) - update.engine.update(update.to_sql) + update.call(update.engine.connection) end def delete(delete) - delete.engine.delete(delete.to_sql) + delete.call(delete.engine.connection) end end include CRUD diff --git a/lib/active_relation/sql.rb b/lib/active_relation/sql.rb index 99cfc66383..0d233b307e 100644 --- a/lib/active_relation/sql.rb +++ b/lib/active_relation/sql.rb @@ -4,9 +4,11 @@ module ActiveRelation delegate :quote_table_name, :quote_column_name, :quote, :to => :engine end - # module Formatting Context / Strategy # unit test me!!! - class Strategy + class Formatter + abstract :attribute, :select, :value + attr_reader :engine + include Quoting def initialize(engine) @@ -14,7 +16,7 @@ module ActiveRelation end end - class Projection < Strategy + class SelectExpression < Formatter def attribute(relation_name, attribute_name, aliaz) "#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}" + (aliaz ? " AS #{quote(aliaz.to_s)}" : "") end @@ -24,13 +26,19 @@ module ActiveRelation end end - class Predicate < Strategy + class WhereClause < Formatter + def value(value) + value + end + end + + class WhereCondition < Formatter def attribute(relation_name, attribute_name, aliaz) "#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}" end - def scalar(scalar, column = nil) - quote(scalar, column) + def value(value, column = nil) + quote(value, column) end def select(select_sql, aliaz) @@ -38,35 +46,29 @@ module ActiveRelation end end - class Selection < Strategy - def scalar(scalar) - scalar - end - end - - class Relation < Strategy + class SelectStatement < Formatter def select(select_sql, aliaz) select_sql end end - class Aggregation < Strategy + class TableReference < Formatter def select(select_sql, aliaz) - "(#{select_sql}) AS #{engine.quote_table_name(aliaz)}" + "(#{select_sql}) AS #{quote_table_name(aliaz)}" end end - class Attribute < Predicate + class Attribute < WhereCondition def initialize(attribute) @attribute, @engine = attribute, attribute.engine end - def scalar(scalar) - quote(scalar, @attribute.column) + def value(value) + quote(value, @attribute.column) end end - class Scalar < Predicate + class Value < WhereCondition end end end
\ No newline at end of file |