aboutsummaryrefslogtreecommitdiffstats
path: root/lib/arel/relations/relation.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/arel/relations/relation.rb')
-rw-r--r--lib/arel/relations/relation.rb158
1 files changed, 158 insertions, 0 deletions
diff --git a/lib/arel/relations/relation.rb b/lib/arel/relations/relation.rb
new file mode 100644
index 0000000000..60fb7bd00a
--- /dev/null
+++ b/lib/arel/relations/relation.rb
@@ -0,0 +1,158 @@
+module Arel
+ class Relation
+ def session
+ Session.new
+ end
+
+ module Enumerable
+ include ::Enumerable
+
+ def each(&block)
+ session.read(self).each(&block)
+ end
+
+ def first
+ session.read(self).first
+ end
+ end
+ include Enumerable
+
+ module Operations
+ def join(other = nil)
+ case other
+ when String
+ Join.new(other, self)
+ when Relation
+ JoinOperation.new("INNER JOIN", self, other)
+ else
+ self
+ end
+ end
+
+ def outer_join(other)
+ JoinOperation.new("LEFT OUTER JOIN", self, other)
+ end
+
+ def [](index)
+ case index
+ when Symbol, String
+ attribute_for_name(index)
+ when Attribute, Expression
+ attribute_for_attribute(index)
+ end
+ end
+
+ def select(*predicates)
+ predicates.all?(&:blank?) ? self : Selection.new(self, *predicates)
+ end
+
+ def project(*attributes)
+ attributes.all?(&:blank?) ? self : Projection.new(self, *attributes)
+ end
+
+ def as(aliaz = nil)
+ aliaz.blank?? self : Alias.new(self, aliaz)
+ end
+
+ def order(*attributes)
+ attributes.all?(&:blank?) ? self : Order.new(self, *attributes)
+ end
+
+ def take(taken = nil)
+ taken.blank?? self : Take.new(self, taken)
+ end
+
+ def skip(skipped = nil)
+ skipped.blank?? self : Skip.new(self, skipped)
+ end
+
+ def group(*groupings)
+ groupings.all?(&:blank?) ? self : Grouping.new(self, *groupings)
+ end
+
+ module Writes
+ def insert(record)
+ session.create Insertion.new(self, record); self
+ end
+
+ def update(assignments)
+ session.update Update.new(self, assignments); self
+ end
+
+ def delete
+ session.delete Deletion.new(self); self
+ end
+ end
+ include Writes
+
+ JoinOperation = Struct.new(:join_sql, :relation1, :relation2) do
+ def on(*predicates)
+ Join.new(join_sql, relation1, relation2, *predicates)
+ end
+ end
+ end
+ include Operations
+
+ module Externalizable
+ def aggregation?
+ false
+ end
+
+ def alias?
+ false
+ end
+ end
+ include Externalizable
+
+ def to_sql(formatter = Sql::SelectStatement.new(engine))
+ formatter.select [
+ "SELECT #{attributes.collect { |a| a.to_sql(Sql::SelectClause.new(engine)) }.join(', ')}",
+ "FROM #{table_sql}",
+ (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 { |o| o.to_sql(Sql::OrderClause.new(engine)) }.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"), self.alias
+ end
+ alias_method :to_s, :to_sql
+
+ def inclusion_predicate_sql
+ "IN"
+ end
+
+ 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 }
+ end
+ end
+ include AttributeAccessors
+
+ def bind(relation)
+ self
+ end
+
+ def format(object)
+ object.to_sql(Sql::WhereCondition.new(engine))
+ end
+
+ def attributes; [] end
+ def selects; [] end
+ def orders; [] end
+ def inserts; [] end
+ def groupings; [] end
+ def joins; nil end
+ def taken; nil end
+ def skipped; nil end
+ def alias; nil end
+ end
+end \ No newline at end of file