1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
module ActiveRelation
class Relation
abstract :attributes, :selects, :orders, :inserts, :groupings, :joins, :limit, :offset, :alias, :hash
hash_on :hash
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)
JoinOperation.new("INNER JOIN", self, other)
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 ::Range
Range.new(self, index)
when Attribute, Expression
attribute_for_attribute(index)
end
end
def include?(attribute)
RelationInclusion.new(attribute, self)
end
def select(*predicates)
Selection.new(self, *predicates.collect {|p| p.bind(self)})
end
def project(*attributes)
Projection.new(self, *attributes.collect {|a| a.bind(self)})
end
def as(aliaz)
Alias.new(self, aliaz)
end
def order(*attributes)
Order.new(self, *attributes.collect {|a| a.bind(self)})
end
def rename(attribute, aliaz)
Rename.new(self, attribute => aliaz)
end
def aggregate(*expressions)
AggregateOperation.new(self, expressions)
end
module Writes
def insert(record)
session.create Insertion.new(self, record.bind(self)); self
end
def update(assignments)
session.update Update.new(self, assignments.bind(self)); 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
AggregateOperation = Struct.new(:relation, :expressions) do
def group(*groupings)
Aggregation.new(relation, :expressions => expressions, :groupings => groupings)
end
end
end
include Operations
def aggregation?
false
end
def alias?
false
end
def to_sql(strategy = Sql::SelectStatement.new(engine))
strategy.select [
"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::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 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 limit; nil end
def offset; nil end
def alias; nil end
end
end
|