arel 0.4.0 → 1.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +24 -0
- data/lib/arel.rb +3 -1
- data/lib/arel/algebra/attributes/attribute.rb +175 -141
- data/lib/arel/algebra/core_extensions.rb +0 -1
- data/lib/arel/algebra/core_extensions/hash.rb +5 -9
- data/lib/arel/algebra/core_extensions/object.rb +0 -4
- data/lib/arel/algebra/expression.rb +37 -24
- data/lib/arel/algebra/header.rb +5 -6
- data/lib/arel/algebra/ordering.rb +13 -5
- data/lib/arel/algebra/predicates.rb +143 -27
- data/lib/arel/algebra/relations.rb +0 -1
- data/lib/arel/algebra/relations/operations/from.rb +10 -2
- data/lib/arel/algebra/relations/operations/group.rb +8 -6
- data/lib/arel/algebra/relations/operations/having.rb +3 -6
- data/lib/arel/algebra/relations/operations/join.rb +52 -18
- data/lib/arel/algebra/relations/operations/lock.rb +4 -6
- data/lib/arel/algebra/relations/operations/order.rb +11 -7
- data/lib/arel/algebra/relations/operations/project.rb +10 -10
- data/lib/arel/algebra/relations/operations/skip.rb +10 -3
- data/lib/arel/algebra/relations/operations/take.rb +10 -3
- data/lib/arel/algebra/relations/operations/where.rb +12 -6
- data/lib/arel/algebra/relations/relation.rb +161 -92
- data/lib/arel/algebra/relations/row.rb +8 -5
- data/lib/arel/algebra/relations/utilities/compound.rb +34 -33
- data/lib/arel/algebra/relations/utilities/externalization.rb +10 -8
- data/lib/arel/algebra/relations/writes.rb +24 -13
- data/lib/arel/algebra/value.rb +41 -2
- data/lib/arel/engines/memory.rb +0 -2
- data/lib/arel/engines/memory/engine.rb +3 -9
- data/lib/arel/engines/memory/relations.rb +0 -3
- data/lib/arel/engines/memory/relations/array.rb +5 -3
- data/lib/arel/engines/memory/relations/operations.rb +2 -60
- data/lib/arel/engines/sql.rb +0 -2
- data/lib/arel/engines/sql/christener.rb +12 -6
- data/lib/arel/engines/sql/compilers/oracle_compiler.rb +34 -23
- data/lib/arel/engines/sql/compilers/postgresql_compiler.rb +23 -15
- data/lib/arel/engines/sql/engine.rb +19 -27
- data/lib/arel/engines/sql/formatters.rb +26 -10
- data/lib/arel/engines/sql/relations.rb +0 -7
- data/lib/arel/engines/sql/relations/compiler.rb +70 -35
- data/lib/arel/engines/sql/relations/table.rb +44 -32
- data/lib/arel/{engines/sql/relations/utilities/recursion.rb → recursion/base_case.rb} +0 -0
- data/lib/arel/session.rb +24 -40
- data/lib/arel/sql_literal.rb +13 -0
- data/lib/arel/version.rb +1 -1
- data/spec/algebra/unit/predicates/inequality_spec.rb +32 -0
- data/spec/algebra/unit/predicates/predicate_spec.rb +22 -0
- data/spec/algebra/unit/primitives/attribute_spec.rb +3 -9
- data/spec/algebra/unit/primitives/expression_spec.rb +1 -7
- data/spec/algebra/unit/relations/join_spec.rb +0 -7
- data/spec/algebra/unit/relations/project_spec.rb +3 -3
- data/spec/algebra/unit/relations/relation_spec.rb +74 -25
- data/spec/algebra/unit/session/session_spec.rb +7 -7
- data/spec/engines/memory/integration/joins/cross_engine_spec.rb +20 -10
- data/spec/engines/memory/unit/relations/array_spec.rb +6 -5
- data/spec/engines/memory/unit/relations/join_spec.rb +7 -6
- data/spec/engines/memory/unit/relations/order_spec.rb +7 -6
- data/spec/engines/memory/unit/relations/project_spec.rb +6 -6
- data/spec/engines/memory/unit/relations/skip_spec.rb +10 -5
- data/spec/engines/memory/unit/relations/take_spec.rb +7 -5
- data/spec/engines/memory/unit/relations/where_spec.rb +13 -9
- data/spec/engines/sql/unit/engine_spec.rb +20 -0
- data/spec/engines/sql/unit/relations/group_spec.rb +2 -2
- data/spec/engines/sql/unit/relations/order_spec.rb +5 -5
- data/spec/engines/sql/unit/relations/project_spec.rb +4 -4
- data/spec/engines/sql/unit/relations/table_spec.rb +0 -7
- data/spec/engines/sql/unit/relations/take_spec.rb +26 -0
- data/spec/engines/sql/unit/relations/where_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -4
- data/spec/sql/christener_spec.rb +70 -0
- data/spec/support/model.rb +7 -2
- metadata +109 -23
- data/lib/arel/algebra/core_extensions/class.rb +0 -32
- data/lib/arel/algebra/relations/operations/alias.rb +0 -7
- data/lib/arel/engines/memory/predicates.rb +0 -99
- data/lib/arel/engines/memory/primitives.rb +0 -27
- data/lib/arel/engines/memory/relations/compound.rb +0 -9
- data/lib/arel/engines/memory/relations/writes.rb +0 -7
- data/lib/arel/engines/sql/predicates.rb +0 -103
- data/lib/arel/engines/sql/primitives.rb +0 -97
- data/lib/arel/engines/sql/relations/operations/alias.rb +0 -5
- data/lib/arel/engines/sql/relations/operations/join.rb +0 -33
- data/lib/arel/engines/sql/relations/relation.rb +0 -65
- data/lib/arel/engines/sql/relations/utilities/compound.rb +0 -10
- data/lib/arel/engines/sql/relations/utilities/externalization.rb +0 -14
- data/lib/arel/engines/sql/relations/writes.rb +0 -19
@@ -1,43 +1,56 @@
|
|
1
1
|
module Arel
|
2
2
|
class Expression < Attribute
|
3
|
-
|
4
|
-
|
5
|
-
delegate :relation, :to => :attribute
|
6
|
-
alias_method :name, :alias
|
3
|
+
attr_reader :attribute
|
4
|
+
alias :name :alias
|
7
5
|
|
8
6
|
def initialize(attribute, aliaz = nil, ancestor = nil)
|
9
|
-
|
7
|
+
super(attribute.relation, aliaz, :alias => aliaz, :ancestor => ancestor)
|
8
|
+
@attribute = attribute
|
10
9
|
end
|
11
10
|
|
12
11
|
def aggregation?
|
13
12
|
true
|
14
13
|
end
|
15
14
|
|
16
|
-
def
|
17
|
-
|
15
|
+
def to_sql(formatter = Sql::SelectClause.new(relation))
|
16
|
+
formatter.expression self
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
19
|
+
def as(aliaz)
|
20
|
+
self.class.new(attribute, aliaz, self)
|
21
|
+
end
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
def bind(new_relation)
|
24
|
+
new_relation == relation ? self : self.class.new(attribute.bind(new_relation), @alias, self)
|
25
|
+
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
end
|
27
|
+
def to_attribute(relation)
|
28
|
+
Attribute.new(relation, @alias, :ancestor => self)
|
32
29
|
end
|
33
|
-
include Transformations
|
34
30
|
end
|
35
31
|
|
36
|
-
class Count
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
class
|
41
|
-
|
32
|
+
class Count < Expression
|
33
|
+
def function_sql; 'COUNT' end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Distinct < Expression
|
37
|
+
def function_sql; 'DISTINCT' end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Sum < Expression
|
41
|
+
def function_sql; 'SUM' end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Maximum < Expression
|
45
|
+
def function_sql; 'MAX' end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Minimum < Expression
|
49
|
+
def function_sql; 'MIN' end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Average < Expression
|
53
|
+
def function_sql; 'AVG' end
|
54
|
+
end
|
42
55
|
end
|
43
56
|
|
data/lib/arel/algebra/header.rb
CHANGED
@@ -4,13 +4,11 @@ module Arel
|
|
4
4
|
|
5
5
|
def initialize(attrs = [])
|
6
6
|
@attributes = attrs.to_ary
|
7
|
-
@names
|
8
|
-
h[k] = @attributes.detect { |a| a.named?(k) }
|
9
|
-
end
|
7
|
+
@names = {}
|
10
8
|
end
|
11
9
|
|
12
|
-
def each
|
13
|
-
to_ary.each
|
10
|
+
def each
|
11
|
+
to_ary.each { |e| yield e }
|
14
12
|
self
|
15
13
|
end
|
16
14
|
|
@@ -55,7 +53,8 @@ module Arel
|
|
55
53
|
end
|
56
54
|
|
57
55
|
def find_by_name(name)
|
58
|
-
|
56
|
+
k = name.to_sym
|
57
|
+
@names[k] ||= @attributes.detect { |a| a.named?(k) }
|
59
58
|
end
|
60
59
|
|
61
60
|
def find_by_attribute(attr)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Arel
|
2
|
-
class Ordering
|
2
|
+
class Ordering < Struct.new(:attribute)
|
3
3
|
delegate :relation, :to => :attribute
|
4
4
|
|
5
5
|
def bind(relation)
|
@@ -9,15 +9,23 @@ module Arel
|
|
9
9
|
def to_ordering
|
10
10
|
self
|
11
11
|
end
|
12
|
+
|
13
|
+
def eval(row1, row2)
|
14
|
+
(attribute.eval(row1) <=> attribute.eval(row2)) * direction
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_sql(formatter = Sql::OrderClause.new(relation))
|
18
|
+
formatter.ordering self
|
19
|
+
end
|
12
20
|
end
|
13
21
|
|
14
22
|
class Ascending < Ordering
|
15
|
-
|
16
|
-
|
23
|
+
def direction; 1 end
|
24
|
+
def direction_sql; 'ASC' end
|
17
25
|
end
|
18
26
|
|
19
27
|
class Descending < Ordering
|
20
|
-
|
21
|
-
|
28
|
+
def direction_sql; 'DESC' end
|
29
|
+
def direction; -1 end
|
22
30
|
end
|
23
31
|
end
|
@@ -19,7 +19,7 @@ module Arel
|
|
19
19
|
end
|
20
20
|
|
21
21
|
class Polyadic < Predicate
|
22
|
-
|
22
|
+
attr_reader :predicates
|
23
23
|
|
24
24
|
def initialize(*predicates)
|
25
25
|
@predicates = predicates
|
@@ -32,14 +32,14 @@ module Arel
|
|
32
32
|
# * <tt>additional_operands</tt> - All possible right-hand operands
|
33
33
|
def self.build(operator, operand1, *additional_operands)
|
34
34
|
new(
|
35
|
-
*additional_operands.uniq.
|
36
|
-
|
35
|
+
*additional_operands.uniq.map do |operand|
|
36
|
+
operator.new(operand1, operand)
|
37
37
|
end
|
38
38
|
)
|
39
39
|
end
|
40
40
|
|
41
41
|
def ==(other)
|
42
|
-
|
42
|
+
super || predicates == other.predicates
|
43
43
|
end
|
44
44
|
|
45
45
|
def bind(relation)
|
@@ -48,14 +48,16 @@ module Arel
|
|
48
48
|
)
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
[:select, :inject, :size].each do |m|
|
55
|
-
return false unless [a1, a2].each {|a| a.respond_to?(m) }
|
51
|
+
def eval(row)
|
52
|
+
predicates.send(compounder) do |operation|
|
53
|
+
operation.eval(row)
|
56
54
|
end
|
57
|
-
|
58
|
-
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_sql(formatter = nil)
|
58
|
+
"(" +
|
59
|
+
predicates.map {|p| p.to_sql(formatter)}.join(" #{predicate_sql} ") +
|
60
|
+
")"
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
@@ -63,61 +65,118 @@ module Arel
|
|
63
65
|
def complement
|
64
66
|
All.new(*predicates.map {|p| p.complement})
|
65
67
|
end
|
68
|
+
|
69
|
+
def compounder; :any? end
|
70
|
+
|
71
|
+
def predicate_sql; "OR" end
|
66
72
|
end
|
67
73
|
|
68
74
|
class All < Polyadic
|
69
75
|
def complement
|
70
76
|
Any.new(*predicates.map {|p| p.complement})
|
71
77
|
end
|
78
|
+
|
79
|
+
def compounder; :all? end
|
80
|
+
|
81
|
+
def predicate_sql; "AND" end
|
72
82
|
end
|
73
83
|
|
74
84
|
class Unary < Predicate
|
75
|
-
|
76
|
-
|
85
|
+
attr_reader :operand
|
86
|
+
|
87
|
+
def initialize operand
|
88
|
+
@operand = operand
|
89
|
+
end
|
77
90
|
|
78
91
|
def bind(relation)
|
79
92
|
self.class.new(operand.find_correlate_in(relation))
|
80
93
|
end
|
94
|
+
|
95
|
+
def == other
|
96
|
+
super || self.class === other && operand == other.operand
|
97
|
+
end
|
98
|
+
|
99
|
+
def eval(row)
|
100
|
+
operand.eval(row).send(operator)
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_sql(formatter = nil)
|
104
|
+
"#{predicate_sql} (#{operand.to_sql(formatter)})"
|
105
|
+
end
|
81
106
|
end
|
82
107
|
|
83
108
|
class Not < Unary
|
84
109
|
def complement
|
85
110
|
operand
|
86
111
|
end
|
112
|
+
|
113
|
+
def eval(row)
|
114
|
+
!operand.eval(row)
|
115
|
+
end
|
116
|
+
|
117
|
+
def predicate_sql; "NOT" end
|
87
118
|
end
|
88
119
|
|
89
|
-
class Binary <
|
90
|
-
|
91
|
-
|
120
|
+
class Binary < Unary
|
121
|
+
attr_reader :operand2
|
122
|
+
alias :operand1 :operand
|
123
|
+
|
124
|
+
def initialize left, right
|
125
|
+
super(left)
|
126
|
+
@operand2 = right
|
127
|
+
end
|
92
128
|
|
93
129
|
def ==(other)
|
94
|
-
|
95
|
-
@operand1 == other.operand1 and
|
96
|
-
@operand2 == other.operand2
|
130
|
+
super && @operand2 == other.operand2
|
97
131
|
end
|
98
132
|
|
99
133
|
def bind(relation)
|
100
134
|
self.class.new(operand1.find_correlate_in(relation), operand2.find_correlate_in(relation))
|
101
135
|
end
|
136
|
+
|
137
|
+
def eval(row)
|
138
|
+
operand1.eval(row).send(operator, operand2.eval(row))
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_sql(formatter = nil)
|
142
|
+
"#{operand1.to_sql} #{predicate_sql} #{operand1.format(operand2)}"
|
143
|
+
end
|
144
|
+
alias :value :to_sql
|
102
145
|
end
|
103
146
|
|
104
|
-
class CompoundPredicate < Binary
|
147
|
+
class CompoundPredicate < Binary
|
148
|
+
def eval(row)
|
149
|
+
eval "operand1.eval(row) #{operator} operand2.eval(row)"
|
150
|
+
end
|
151
|
+
|
152
|
+
def to_sql(formatter = nil)
|
153
|
+
"(#{operand1.to_sql(formatter)} #{predicate_sql} #{operand2.to_sql(formatter)})"
|
154
|
+
end
|
155
|
+
end
|
105
156
|
|
106
157
|
class And < CompoundPredicate
|
107
158
|
def complement
|
108
159
|
Or.new(operand1.complement, operand2.complement)
|
109
160
|
end
|
161
|
+
|
162
|
+
def operator; :and end
|
163
|
+
|
164
|
+
def predicate_sql; "AND" end
|
110
165
|
end
|
111
166
|
|
112
167
|
class Or < CompoundPredicate
|
113
168
|
def complement
|
114
169
|
And.new(operand1.complement, operand2.complement)
|
115
170
|
end
|
171
|
+
|
172
|
+
def operator; :or end
|
173
|
+
|
174
|
+
def predicate_sql; "OR" end
|
116
175
|
end
|
117
176
|
|
118
177
|
class Equality < Binary
|
119
178
|
def ==(other)
|
120
|
-
|
179
|
+
self.class === other and
|
121
180
|
((operand1 == other.operand1 and operand2 == other.operand2) or
|
122
181
|
(operand1 == other.operand2 and operand2 == other.operand1))
|
123
182
|
end
|
@@ -125,66 +184,123 @@ module Arel
|
|
125
184
|
def complement
|
126
185
|
Inequality.new(operand1, operand2)
|
127
186
|
end
|
128
|
-
end
|
129
187
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
(operand1 == other.operand2 and operand2 == other.operand1))
|
188
|
+
def operator; :== end
|
189
|
+
|
190
|
+
def predicate_sql
|
191
|
+
operand2.equality_predicate_sql
|
135
192
|
end
|
193
|
+
end
|
136
194
|
|
195
|
+
class Inequality < Equality
|
137
196
|
def complement
|
138
197
|
Equality.new(operand1, operand2)
|
139
198
|
end
|
199
|
+
|
200
|
+
def operator; :"!=" end
|
201
|
+
def eval(row)
|
202
|
+
operand1.eval(row) != operand2.eval(row)
|
203
|
+
end
|
204
|
+
|
205
|
+
def predicate_sql
|
206
|
+
operand2.inequality_predicate_sql
|
207
|
+
end
|
140
208
|
end
|
141
209
|
|
142
210
|
class GreaterThanOrEqualTo < Binary
|
143
211
|
def complement
|
144
212
|
LessThan.new(operand1, operand2)
|
145
213
|
end
|
214
|
+
|
215
|
+
def operator; :>= end
|
216
|
+
|
217
|
+
def predicate_sql; '>=' end
|
146
218
|
end
|
147
219
|
|
148
220
|
class GreaterThan < Binary
|
149
221
|
def complement
|
150
222
|
LessThanOrEqualTo.new(operand1, operand2)
|
151
223
|
end
|
224
|
+
|
225
|
+
def operator; :> end
|
226
|
+
|
227
|
+
def predicate_sql; '>' end
|
152
228
|
end
|
153
229
|
|
154
230
|
class LessThanOrEqualTo < Binary
|
155
231
|
def complement
|
156
232
|
GreaterThan.new(operand1, operand2)
|
157
233
|
end
|
234
|
+
|
235
|
+
def operator; :<= end
|
236
|
+
|
237
|
+
def predicate_sql; '<=' end
|
158
238
|
end
|
159
239
|
|
160
240
|
class LessThan < Binary
|
161
241
|
def complement
|
162
242
|
GreaterThanOrEqualTo.new(operand1, operand2)
|
163
243
|
end
|
244
|
+
|
245
|
+
def operator; :< end
|
246
|
+
|
247
|
+
def predicate_sql; '<' end
|
164
248
|
end
|
165
249
|
|
166
250
|
class Match < Binary
|
167
251
|
def complement
|
168
252
|
NotMatch.new(operand1, operand2)
|
169
253
|
end
|
254
|
+
|
255
|
+
def operator; :=~ end
|
256
|
+
|
257
|
+
def predicate_sql; 'LIKE' end
|
170
258
|
end
|
171
259
|
|
172
260
|
class NotMatch < Binary
|
173
261
|
def complement
|
174
262
|
Match.new(operand1, operand2)
|
175
263
|
end
|
264
|
+
|
265
|
+
def eval(row)
|
266
|
+
operand1.eval(row) !~ operand2.eval(row)
|
267
|
+
end
|
268
|
+
|
269
|
+
def predicate_sql; 'NOT LIKE' end
|
176
270
|
end
|
177
271
|
|
178
272
|
class In < Binary
|
179
273
|
def complement
|
180
274
|
NotIn.new(operand1, operand2)
|
181
275
|
end
|
276
|
+
|
277
|
+
def eval(row)
|
278
|
+
operand2.eval(row).include?(operand1.eval(row))
|
279
|
+
end
|
280
|
+
|
281
|
+
def to_sql(formatter = nil)
|
282
|
+
if operand2.is_a?(Range) && operand2.exclude_end?
|
283
|
+
GreaterThanOrEqualTo.new(operand1, operand2.begin).and(
|
284
|
+
LessThan.new(operand1, operand2.end)
|
285
|
+
).to_sql(formatter)
|
286
|
+
else
|
287
|
+
super
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def predicate_sql; operand2.inclusion_predicate_sql end
|
182
292
|
end
|
183
293
|
|
184
294
|
class NotIn < Binary
|
185
295
|
def complement
|
186
296
|
In.new(operand1, operand2)
|
187
297
|
end
|
298
|
+
|
299
|
+
def eval(row)
|
300
|
+
!(operand2.eval(row).include?(operand1.eval(row)))
|
301
|
+
end
|
302
|
+
|
303
|
+
def predicate_sql; operand2.exclusion_predicate_sql end
|
188
304
|
end
|
189
305
|
end
|
190
306
|
end
|