arel 3.0.3 → 4.0.0
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/.travis.yml +2 -4
- data/Gemfile +2 -2
- data/History.txt +3 -54
- data/Manifest.txt +8 -2
- data/README.markdown +8 -4
- data/Rakefile +1 -1
- data/arel.gemspec +21 -29
- data/lib/arel/crud.rb +3 -3
- data/lib/arel/nodes/and.rb +10 -0
- data/lib/arel/nodes/binary.rb +11 -0
- data/lib/arel/nodes/extract.rb +11 -0
- data/lib/arel/nodes/false.rb +7 -0
- data/lib/arel/nodes/function.rb +11 -0
- data/lib/arel/nodes/grouping.rb +7 -0
- data/lib/arel/nodes/insert_statement.rb +12 -0
- data/lib/arel/nodes/named_function.rb +9 -0
- data/lib/arel/nodes/select_core.rb +20 -0
- data/lib/arel/nodes/select_statement.rb +15 -1
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/terminal.rb +7 -0
- data/lib/arel/nodes/true.rb +7 -0
- data/lib/arel/nodes/unary.rb +10 -1
- data/lib/arel/nodes/update_statement.rb +15 -0
- data/lib/arel/nodes/window.rb +30 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +18 -2
- data/lib/arel/select_manager.rb +6 -2
- data/lib/arel/table.rb +14 -1
- data/lib/arel/tree_manager.rb +0 -2
- data/lib/arel/visitors/bind_visitor.rb +10 -0
- data/lib/arel/visitors/dot.rb +2 -2
- data/lib/arel/visitors/to_sql.rb +142 -31
- data/lib/arel.rb +1 -3
- data/test/nodes/test_and.rb +20 -0
- data/test/nodes/test_as.rb +12 -0
- data/test/nodes/test_ascending.rb +10 -0
- data/test/nodes/test_bin.rb +10 -0
- data/test/nodes/test_count.rb +12 -0
- data/test/nodes/test_delete_statement.rb +20 -0
- data/test/nodes/test_descending.rb +10 -0
- data/test/nodes/test_distinct.rb +20 -0
- data/test/nodes/test_equality.rb +10 -0
- data/test/nodes/test_extract.rb +14 -0
- data/test/nodes/test_false.rb +20 -0
- data/test/nodes/test_grouping.rb +25 -0
- data/test/nodes/test_infix_operation.rb +10 -0
- data/test/nodes/test_insert_statement.rb +24 -0
- data/test/nodes/test_named_function.rb +16 -0
- data/test/nodes/test_not.rb +12 -0
- data/test/nodes/test_or.rb +12 -0
- data/test/nodes/test_over.rb +18 -0
- data/test/nodes/test_select_core.rb +38 -0
- data/test/nodes/test_select_statement.rb +36 -0
- data/test/nodes/test_sql_literal.rb +10 -0
- data/test/nodes/test_sum.rb +12 -0
- data/test/nodes/test_table_alias.rb +36 -0
- data/test/nodes/test_true.rb +21 -0
- data/test/nodes/test_update_statement.rb +40 -0
- data/test/nodes/test_window.rb +73 -0
- data/test/support/fake_record.rb +5 -1
- data/test/test_attributes.rb +12 -0
- data/test/test_insert_manager.rb +0 -2
- data/test/test_select_manager.rb +10 -5
- data/test/test_table.rb +24 -0
- data/test/test_update_manager.rb +8 -0
- data/test/visitors/test_bind_visitor.rb +20 -1
- data/test/visitors/test_to_sql.rb +78 -0
- metadata +84 -82
- data/lib/arel/nodes/ordering.rb +0 -6
- data/lib/arel/relation.rb +0 -6
data/lib/arel/nodes/window.rb
CHANGED
|
@@ -17,7 +17,6 @@ module Arel
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def frame(expr)
|
|
20
|
-
raise ArgumentError, "Window frame cannot be set more than once" if @frame
|
|
21
20
|
@framing = expr
|
|
22
21
|
end
|
|
23
22
|
|
|
@@ -33,6 +32,17 @@ module Arel
|
|
|
33
32
|
super
|
|
34
33
|
@orders = @orders.map { |x| x.clone }
|
|
35
34
|
end
|
|
35
|
+
|
|
36
|
+
def hash
|
|
37
|
+
[@orders, @framing].hash
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def eql? other
|
|
41
|
+
self.class == other.class &&
|
|
42
|
+
self.orders == other.orders &&
|
|
43
|
+
self.framing == other.framing
|
|
44
|
+
end
|
|
45
|
+
alias :== :eql?
|
|
36
46
|
end
|
|
37
47
|
|
|
38
48
|
class NamedWindow < Window
|
|
@@ -47,6 +57,15 @@ module Arel
|
|
|
47
57
|
super
|
|
48
58
|
@name = other.name.clone
|
|
49
59
|
end
|
|
60
|
+
|
|
61
|
+
def hash
|
|
62
|
+
super ^ @name.hash
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def eql? other
|
|
66
|
+
super && self.name == other.name
|
|
67
|
+
end
|
|
68
|
+
alias :== :eql?
|
|
50
69
|
end
|
|
51
70
|
|
|
52
71
|
class Rows < Unary
|
|
@@ -61,7 +80,15 @@ module Arel
|
|
|
61
80
|
end
|
|
62
81
|
end
|
|
63
82
|
|
|
64
|
-
class CurrentRow <
|
|
83
|
+
class CurrentRow < Node
|
|
84
|
+
def hash
|
|
85
|
+
self.class.hash
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def eql? other
|
|
89
|
+
self.class == other.class
|
|
90
|
+
end
|
|
91
|
+
end
|
|
65
92
|
|
|
66
93
|
class Preceding < Unary
|
|
67
94
|
def initialize(expr = nil)
|
|
@@ -75,4 +102,4 @@ module Arel
|
|
|
75
102
|
end
|
|
76
103
|
end
|
|
77
104
|
end
|
|
78
|
-
end
|
|
105
|
+
end
|
data/lib/arel/nodes.rb
CHANGED
data/lib/arel/predications.rb
CHANGED
|
@@ -29,7 +29,15 @@ module Arel
|
|
|
29
29
|
when Arel::SelectManager
|
|
30
30
|
Arel::Nodes::In.new(self, other.ast)
|
|
31
31
|
when Range
|
|
32
|
-
if other.
|
|
32
|
+
if other.begin == -Float::INFINITY && other.end == Float::INFINITY
|
|
33
|
+
Nodes::NotIn.new self, []
|
|
34
|
+
elsif other.end == Float::INFINITY
|
|
35
|
+
Nodes::GreaterThanOrEqual.new(self, other.begin)
|
|
36
|
+
elsif other.begin == -Float::INFINITY && other.exclude_end?
|
|
37
|
+
Nodes::LessThan.new(self, other.end)
|
|
38
|
+
elsif other.begin == -Float::INFINITY
|
|
39
|
+
Nodes::LessThanOrEqual.new(self, other.end)
|
|
40
|
+
elsif other.exclude_end?
|
|
33
41
|
left = Nodes::GreaterThanOrEqual.new(self, other.begin)
|
|
34
42
|
right = Nodes::LessThan.new(self, other.end)
|
|
35
43
|
Nodes::And.new [left, right]
|
|
@@ -54,7 +62,15 @@ module Arel
|
|
|
54
62
|
when Arel::SelectManager
|
|
55
63
|
Arel::Nodes::NotIn.new(self, other.ast)
|
|
56
64
|
when Range
|
|
57
|
-
if other.
|
|
65
|
+
if other.begin == -Float::INFINITY && other.end == Float::INFINITY
|
|
66
|
+
Nodes::In.new self, []
|
|
67
|
+
elsif other.end == Float::INFINITY
|
|
68
|
+
Nodes::LessThan.new(self, other.begin)
|
|
69
|
+
elsif other.begin == -Float::INFINITY && other.exclude_end?
|
|
70
|
+
Nodes::GreaterThanOrEqual.new(self, other.end)
|
|
71
|
+
elsif other.begin == -Float::INFINITY
|
|
72
|
+
Nodes::GreaterThan.new(self, other.end)
|
|
73
|
+
elsif other.exclude_end?
|
|
58
74
|
left = Nodes::LessThan.new(self, other.begin)
|
|
59
75
|
right = Nodes::GreaterThanOrEqual.new(self, other.end)
|
|
60
76
|
Nodes::Or.new left, right
|
data/lib/arel/select_manager.rb
CHANGED
|
@@ -141,6 +141,10 @@ module Arel
|
|
|
141
141
|
self
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
def projections
|
|
145
|
+
@ctx.projections
|
|
146
|
+
end
|
|
147
|
+
|
|
144
148
|
def projections= projections
|
|
145
149
|
@ctx.projections = projections
|
|
146
150
|
end
|
|
@@ -166,7 +170,7 @@ module Arel
|
|
|
166
170
|
end
|
|
167
171
|
|
|
168
172
|
def wheres
|
|
169
|
-
warn "#{caller[0]}: SelectManager#wheres is deprecated and will be removed in
|
|
173
|
+
warn "#{caller[0]}: SelectManager#wheres is deprecated and will be removed in Arel 4.0.0 with no replacement"
|
|
170
174
|
Compatibility::Wheres.new @engine.connection, @ctx.wheres
|
|
171
175
|
end
|
|
172
176
|
|
|
@@ -272,7 +276,7 @@ module Arel
|
|
|
272
276
|
def insert values
|
|
273
277
|
if $VERBOSE
|
|
274
278
|
warn <<-eowarn
|
|
275
|
-
insert (#{caller.first}) is deprecated and will be removed in
|
|
279
|
+
insert (#{caller.first}) is deprecated and will be removed in Arel 4.0.0. Please
|
|
276
280
|
switch to `compile_insert`
|
|
277
281
|
eowarn
|
|
278
282
|
end
|
data/lib/arel/table.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Arel
|
|
|
32
32
|
def primary_key
|
|
33
33
|
if $VERBOSE
|
|
34
34
|
warn <<-eowarn
|
|
35
|
-
primary_key (#{caller.first}) is deprecated and will be removed in
|
|
35
|
+
primary_key (#{caller.first}) is deprecated and will be removed in Arel 4.0.0
|
|
36
36
|
eowarn
|
|
37
37
|
end
|
|
38
38
|
@primary_key ||= begin
|
|
@@ -123,6 +123,19 @@ Arel 4.0.0 with no replacement. PEW PEW PEW!!!
|
|
|
123
123
|
InsertManager.new(@engine)
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
+
def hash
|
|
127
|
+
[@name, @engine, @aliases, @table_alias].hash
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def eql? other
|
|
131
|
+
self.class == other.class &&
|
|
132
|
+
self.name == other.name &&
|
|
133
|
+
self.engine == other.engine &&
|
|
134
|
+
self.aliases == other.aliases &&
|
|
135
|
+
self.table_alias == other.table_alias
|
|
136
|
+
end
|
|
137
|
+
alias :== :eql?
|
|
138
|
+
|
|
126
139
|
private
|
|
127
140
|
|
|
128
141
|
def attributes_for columns
|
data/lib/arel/tree_manager.rb
CHANGED
|
@@ -12,6 +12,15 @@ module Arel
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
private
|
|
15
|
+
|
|
16
|
+
def visit_Arel_Nodes_Assignment o
|
|
17
|
+
if o.right.is_a? Arel::Nodes::BindParam
|
|
18
|
+
"#{visit o.left} = #{visit o.right}"
|
|
19
|
+
else
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
15
24
|
def visit_Arel_Nodes_BindParam o
|
|
16
25
|
if @block
|
|
17
26
|
@block.call
|
|
@@ -19,6 +28,7 @@ module Arel
|
|
|
19
28
|
super
|
|
20
29
|
end
|
|
21
30
|
end
|
|
31
|
+
|
|
22
32
|
end
|
|
23
33
|
end
|
|
24
34
|
end
|
data/lib/arel/visitors/dot.rb
CHANGED
|
@@ -65,7 +65,6 @@ module Arel
|
|
|
65
65
|
visit_edge o, "expr"
|
|
66
66
|
end
|
|
67
67
|
alias :visit_Arel_Nodes_Group :unary
|
|
68
|
-
alias :visit_Arel_Nodes_BindParam :unary
|
|
69
68
|
alias :visit_Arel_Nodes_Grouping :unary
|
|
70
69
|
alias :visit_Arel_Nodes_Having :unary
|
|
71
70
|
alias :visit_Arel_Nodes_Limit :unary
|
|
@@ -195,6 +194,7 @@ module Arel
|
|
|
195
194
|
alias :visit_TrueClass :visit_String
|
|
196
195
|
alias :visit_FalseClass :visit_String
|
|
197
196
|
alias :visit_Arel_SqlLiteral :visit_String
|
|
197
|
+
alias :visit_Arel_Nodes_BindParam :visit_String
|
|
198
198
|
alias :visit_Fixnum :visit_String
|
|
199
199
|
alias :visit_BigDecimal :visit_String
|
|
200
200
|
alias :visit_Float :visit_String
|
|
@@ -254,7 +254,7 @@ module Arel
|
|
|
254
254
|
end
|
|
255
255
|
|
|
256
256
|
def to_dot
|
|
257
|
-
"digraph \"
|
|
257
|
+
"digraph \"Arel\" {\nnode [width=0.375,height=0.25,shape=record];\n" +
|
|
258
258
|
@nodes.map { |node|
|
|
259
259
|
label = "<f0>#{node.name}"
|
|
260
260
|
|
data/lib/arel/visitors/to_sql.rb
CHANGED
|
@@ -4,6 +4,55 @@ require 'date'
|
|
|
4
4
|
module Arel
|
|
5
5
|
module Visitors
|
|
6
6
|
class ToSql < Arel::Visitors::Visitor
|
|
7
|
+
##
|
|
8
|
+
# This is some roflscale crazy stuff. I'm roflscaling this because
|
|
9
|
+
# building SQL queries is a hotspot. I will explain the roflscale so that
|
|
10
|
+
# others will not rm this code.
|
|
11
|
+
#
|
|
12
|
+
# In YARV, string literals in a method body will get duped when the byte
|
|
13
|
+
# code is executed. Let's take a look:
|
|
14
|
+
#
|
|
15
|
+
# > puts RubyVM::InstructionSequence.new('def foo; "bar"; end').disasm
|
|
16
|
+
#
|
|
17
|
+
# == disasm: <RubyVM::InstructionSequence:foo@<compiled>>=====
|
|
18
|
+
# 0000 trace 8
|
|
19
|
+
# 0002 trace 1
|
|
20
|
+
# 0004 putstring "bar"
|
|
21
|
+
# 0006 trace 16
|
|
22
|
+
# 0008 leave
|
|
23
|
+
#
|
|
24
|
+
# The `putstring` bytecode will dup the string and push it on the stack.
|
|
25
|
+
# In many cases in our SQL visitor, that string is never mutated, so there
|
|
26
|
+
# is no need to dup the literal.
|
|
27
|
+
#
|
|
28
|
+
# If we change to a constant lookup, the string will not be duped, and we
|
|
29
|
+
# can reduce the objects in our system:
|
|
30
|
+
#
|
|
31
|
+
# > puts RubyVM::InstructionSequence.new('BAR = "bar"; def foo; BAR; end').disasm
|
|
32
|
+
#
|
|
33
|
+
# == disasm: <RubyVM::InstructionSequence:foo@<compiled>>========
|
|
34
|
+
# 0000 trace 8
|
|
35
|
+
# 0002 trace 1
|
|
36
|
+
# 0004 getinlinecache 11, <ic:0>
|
|
37
|
+
# 0007 getconstant :BAR
|
|
38
|
+
# 0009 setinlinecache <ic:0>
|
|
39
|
+
# 0011 trace 16
|
|
40
|
+
# 0013 leave
|
|
41
|
+
#
|
|
42
|
+
# `getconstant` should be a hash lookup, and no object is duped when the
|
|
43
|
+
# value of the constant is pushed on the stack. Hence the crazy
|
|
44
|
+
# constants below.
|
|
45
|
+
|
|
46
|
+
WHERE = ' WHERE ' # :nodoc:
|
|
47
|
+
SPACE = ' ' # :nodoc:
|
|
48
|
+
COMMA = ', ' # :nodoc:
|
|
49
|
+
GROUP_BY = ' GROUP BY ' # :nodoc:
|
|
50
|
+
ORDER_BY = ' ORDER BY ' # :nodoc:
|
|
51
|
+
WINDOW = ' WINDOW ' # :nodoc:
|
|
52
|
+
AND = ' AND ' # :nodoc:
|
|
53
|
+
|
|
54
|
+
DISTINCT = 'DISTINCT' # :nodoc:
|
|
55
|
+
|
|
7
56
|
attr_accessor :last_column
|
|
8
57
|
|
|
9
58
|
def initialize connection
|
|
@@ -23,7 +72,7 @@ module Arel
|
|
|
23
72
|
def visit_Arel_Nodes_DeleteStatement o
|
|
24
73
|
[
|
|
25
74
|
"DELETE FROM #{visit o.relation}",
|
|
26
|
-
("WHERE #{o.wheres.map { |x| visit x }.join
|
|
75
|
+
("WHERE #{o.wheres.map { |x| visit x }.join AND}" unless o.wheres.empty?)
|
|
27
76
|
].compact.join ' '
|
|
28
77
|
end
|
|
29
78
|
|
|
@@ -47,7 +96,7 @@ module Arel
|
|
|
47
96
|
unless key
|
|
48
97
|
warn(<<-eowarn) if $VERBOSE
|
|
49
98
|
(#{caller.first}) Using UpdateManager without setting UpdateManager#key is
|
|
50
|
-
deprecated and support will be removed in
|
|
99
|
+
deprecated and support will be removed in Arel 4.0.0. Please set the primary
|
|
51
100
|
key on UpdateManager using UpdateManager#key=
|
|
52
101
|
eowarn
|
|
53
102
|
key = o.relation.primary_key
|
|
@@ -98,11 +147,11 @@ key on UpdateManager using UpdateManager#key=
|
|
|
98
147
|
|
|
99
148
|
return nil unless table_exists? table
|
|
100
149
|
|
|
101
|
-
column_cache
|
|
150
|
+
column_cache(table)[name]
|
|
102
151
|
end
|
|
103
152
|
|
|
104
|
-
def column_cache
|
|
105
|
-
@schema_cache.columns_hash
|
|
153
|
+
def column_cache(table)
|
|
154
|
+
@schema_cache.columns_hash(table)
|
|
106
155
|
end
|
|
107
156
|
|
|
108
157
|
def visit_Arel_Nodes_Values o
|
|
@@ -116,28 +165,80 @@ key on UpdateManager using UpdateManager#key=
|
|
|
116
165
|
end
|
|
117
166
|
|
|
118
167
|
def visit_Arel_Nodes_SelectStatement o
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
168
|
+
str = ''
|
|
169
|
+
|
|
170
|
+
if o.with
|
|
171
|
+
str << visit(o.with)
|
|
172
|
+
str << SPACE
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
o.cores.each { |x| str << visit_Arel_Nodes_SelectCore(x) }
|
|
176
|
+
|
|
177
|
+
unless o.orders.empty?
|
|
178
|
+
str << SPACE
|
|
179
|
+
str << ORDER_BY
|
|
180
|
+
len = o.orders.length - 1
|
|
181
|
+
o.orders.each_with_index { |x, i|
|
|
182
|
+
str << visit(x)
|
|
183
|
+
str << COMMA unless len == i
|
|
184
|
+
}
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
str << " #{visit(o.limit)}" if o.limit
|
|
188
|
+
str << " #{visit(o.offset)}" if o.offset
|
|
189
|
+
str << " #{visit(o.lock)}" if o.lock
|
|
190
|
+
|
|
191
|
+
str.strip!
|
|
192
|
+
str
|
|
127
193
|
end
|
|
128
194
|
|
|
129
195
|
def visit_Arel_Nodes_SelectCore o
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
196
|
+
str = "SELECT"
|
|
197
|
+
|
|
198
|
+
str << " #{visit(o.top)}" if o.top
|
|
199
|
+
str << " #{visit(o.set_quantifier)}" if o.set_quantifier
|
|
200
|
+
|
|
201
|
+
unless o.projections.empty?
|
|
202
|
+
str << SPACE
|
|
203
|
+
len = o.projections.length - 1
|
|
204
|
+
o.projections.each_with_index do |x, i|
|
|
205
|
+
str << visit(x)
|
|
206
|
+
str << COMMA unless len == i
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
str << " FROM #{visit(o.source)}" if o.source && !o.source.empty?
|
|
211
|
+
|
|
212
|
+
unless o.wheres.empty?
|
|
213
|
+
str << WHERE
|
|
214
|
+
len = o.wheres.length - 1
|
|
215
|
+
o.wheres.each_with_index do |x, i|
|
|
216
|
+
str << visit(x)
|
|
217
|
+
str << AND unless len == i
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
unless o.groups.empty?
|
|
222
|
+
str << GROUP_BY
|
|
223
|
+
len = o.groups.length - 1
|
|
224
|
+
o.groups.each_with_index do |x, i|
|
|
225
|
+
str << visit(x)
|
|
226
|
+
str << COMMA unless len == i
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
str << " #{visit(o.having)}" if o.having
|
|
231
|
+
|
|
232
|
+
unless o.windows.empty?
|
|
233
|
+
str << WINDOW
|
|
234
|
+
len = o.windows.length - 1
|
|
235
|
+
o.windows.each_with_index do |x, i|
|
|
236
|
+
str << visit(x)
|
|
237
|
+
str << COMMA unless len == i
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
str
|
|
141
242
|
end
|
|
142
243
|
|
|
143
244
|
def visit_Arel_Nodes_Bin o
|
|
@@ -145,7 +246,7 @@ key on UpdateManager using UpdateManager#key=
|
|
|
145
246
|
end
|
|
146
247
|
|
|
147
248
|
def visit_Arel_Nodes_Distinct o
|
|
148
|
-
|
|
249
|
+
DISTINCT
|
|
149
250
|
end
|
|
150
251
|
|
|
151
252
|
def visit_Arel_Nodes_DistinctOn o
|
|
@@ -254,6 +355,10 @@ key on UpdateManager using UpdateManager#key=
|
|
|
254
355
|
"(#{visit o.expr})"
|
|
255
356
|
end
|
|
256
357
|
|
|
358
|
+
def visit_Arel_SelectManager o
|
|
359
|
+
"(#{o.to_sql.rstrip})"
|
|
360
|
+
end
|
|
361
|
+
|
|
257
362
|
def visit_Arel_Nodes_Ascending o
|
|
258
363
|
"#{visit o.expr} ASC"
|
|
259
364
|
end
|
|
@@ -283,22 +388,22 @@ key on UpdateManager using UpdateManager#key=
|
|
|
283
388
|
end
|
|
284
389
|
|
|
285
390
|
def visit_Arel_Nodes_Sum o
|
|
286
|
-
"SUM(#{o.expressions.map { |x|
|
|
391
|
+
"SUM(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
|
287
392
|
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
|
288
393
|
end
|
|
289
394
|
|
|
290
395
|
def visit_Arel_Nodes_Max o
|
|
291
|
-
"MAX(#{o.expressions.map { |x|
|
|
396
|
+
"MAX(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
|
292
397
|
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
|
293
398
|
end
|
|
294
399
|
|
|
295
400
|
def visit_Arel_Nodes_Min o
|
|
296
|
-
"MIN(#{o.expressions.map { |x|
|
|
401
|
+
"MIN(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
|
297
402
|
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
|
298
403
|
end
|
|
299
404
|
|
|
300
405
|
def visit_Arel_Nodes_Avg o
|
|
301
|
-
"AVG(#{o.expressions.map { |x|
|
|
406
|
+
"AVG(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
|
302
407
|
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
|
303
408
|
end
|
|
304
409
|
|
|
@@ -350,7 +455,12 @@ key on UpdateManager using UpdateManager#key=
|
|
|
350
455
|
end
|
|
351
456
|
|
|
352
457
|
def visit_Arel_Nodes_InnerJoin o
|
|
353
|
-
"INNER JOIN #{visit o.left}
|
|
458
|
+
s = "INNER JOIN #{visit o.left}"
|
|
459
|
+
if o.right
|
|
460
|
+
s << SPACE
|
|
461
|
+
s << visit(o.right)
|
|
462
|
+
end
|
|
463
|
+
s
|
|
354
464
|
end
|
|
355
465
|
|
|
356
466
|
def visit_Arel_Nodes_On o
|
|
@@ -475,10 +585,11 @@ key on UpdateManager using UpdateManager#key=
|
|
|
475
585
|
alias :visit_Arel_Nodes_Division :visit_Arel_Nodes_InfixOperation
|
|
476
586
|
|
|
477
587
|
def visit_Array o
|
|
478
|
-
o.
|
|
588
|
+
o.map { |x| visit x }.join(', ')
|
|
479
589
|
end
|
|
480
590
|
|
|
481
591
|
def quote value, column = nil
|
|
592
|
+
return value if Arel::Nodes::SqlLiteral === value
|
|
482
593
|
@connection.quote value, column
|
|
483
594
|
end
|
|
484
595
|
|
data/lib/arel.rb
CHANGED
|
@@ -12,8 +12,6 @@ require 'arel/attributes'
|
|
|
12
12
|
require 'arel/compatibility/wheres'
|
|
13
13
|
|
|
14
14
|
#### these are deprecated
|
|
15
|
-
# The Arel::Relation constant is referenced in Rails
|
|
16
|
-
require 'arel/relation'
|
|
17
15
|
require 'arel/expression'
|
|
18
16
|
####
|
|
19
17
|
|
|
@@ -34,7 +32,7 @@ require 'arel/sql_literal'
|
|
|
34
32
|
####
|
|
35
33
|
|
|
36
34
|
module Arel
|
|
37
|
-
VERSION = '
|
|
35
|
+
VERSION = '4.0.0'
|
|
38
36
|
|
|
39
37
|
def self.sql raw_sql
|
|
40
38
|
Arel::Nodes::SqlLiteral.new raw_sql
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'helper'
|
|
2
|
+
|
|
3
|
+
module Arel
|
|
4
|
+
module Nodes
|
|
5
|
+
describe 'And' do
|
|
6
|
+
describe 'equality' do
|
|
7
|
+
it 'is equal with equal ivars' do
|
|
8
|
+
array = [And.new(['foo', 'bar']), And.new(['foo', 'bar'])]
|
|
9
|
+
assert_equal 1, array.uniq.size
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'is not equal with different ivars' do
|
|
13
|
+
array = [And.new(['foo', 'bar']), And.new(['foo', 'baz'])]
|
|
14
|
+
assert_equal 2, array.uniq.size
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
data/test/nodes/test_as.rb
CHANGED
|
@@ -17,6 +17,18 @@ module Arel
|
|
|
17
17
|
assert_kind_of Arel::Nodes::SqlLiteral, as.right
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
|
+
|
|
21
|
+
describe 'equality' do
|
|
22
|
+
it 'is equal with equal ivars' do
|
|
23
|
+
array = [As.new('foo', 'bar'), As.new('foo', 'bar')]
|
|
24
|
+
assert_equal 1, array.uniq.size
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'is not equal with different ivars' do
|
|
28
|
+
array = [As.new('foo', 'bar'), As.new('foo', 'baz')]
|
|
29
|
+
assert_equal 2, array.uniq.size
|
|
30
|
+
end
|
|
31
|
+
end
|
|
20
32
|
end
|
|
21
33
|
end
|
|
22
34
|
end
|
|
@@ -29,6 +29,16 @@ module Arel
|
|
|
29
29
|
ascending = Ascending.new 'zomg'
|
|
30
30
|
assert !ascending.descending?
|
|
31
31
|
end
|
|
32
|
+
|
|
33
|
+
def test_equality_with_same_ivars
|
|
34
|
+
array = [Ascending.new('zomg'), Ascending.new('zomg')]
|
|
35
|
+
assert_equal 1, array.uniq.size
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_inequality_with_different_ivars
|
|
39
|
+
array = [Ascending.new('zomg'), Ascending.new('zomg!')]
|
|
40
|
+
assert_equal 2, array.uniq.size
|
|
41
|
+
end
|
|
32
42
|
end
|
|
33
43
|
end
|
|
34
44
|
end
|
data/test/nodes/test_bin.rb
CHANGED
|
@@ -18,6 +18,16 @@ module Arel
|
|
|
18
18
|
node = Arel::Nodes::Bin.new(Arel.sql('zomg'))
|
|
19
19
|
assert_equal 'BINARY zomg', viz.accept(node)
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
def test_equality_with_same_ivars
|
|
23
|
+
array = [Bin.new('zomg'), Bin.new('zomg')]
|
|
24
|
+
assert_equal 1, array.uniq.size
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_inequality_with_different_ivars
|
|
28
|
+
array = [Bin.new('zomg'), Bin.new('zomg!')]
|
|
29
|
+
assert_equal 2, array.uniq.size
|
|
30
|
+
end
|
|
21
31
|
end
|
|
22
32
|
end
|
|
23
33
|
end
|
data/test/nodes/test_count.rb
CHANGED
|
@@ -24,4 +24,16 @@ describe Arel::Nodes::Count do
|
|
|
24
24
|
}
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
|
+
|
|
28
|
+
describe 'equality' do
|
|
29
|
+
it 'is equal with equal ivars' do
|
|
30
|
+
array = [Arel::Nodes::Count.new('foo'), Arel::Nodes::Count.new('foo')]
|
|
31
|
+
assert_equal 1, array.uniq.size
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'is not equal with different ivars' do
|
|
35
|
+
array = [Arel::Nodes::Count.new('foo'), Arel::Nodes::Count.new('foo!')]
|
|
36
|
+
assert_equal 2, array.uniq.size
|
|
37
|
+
end
|
|
38
|
+
end
|
|
27
39
|
end
|
|
@@ -11,4 +11,24 @@ describe Arel::Nodes::DeleteStatement do
|
|
|
11
11
|
dolly.wheres.wont_be_same_as statement.wheres
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
describe 'equality' do
|
|
16
|
+
it 'is equal with equal ivars' do
|
|
17
|
+
statement1 = Arel::Nodes::DeleteStatement.new
|
|
18
|
+
statement1.wheres = %w[a b c]
|
|
19
|
+
statement2 = Arel::Nodes::DeleteStatement.new
|
|
20
|
+
statement2.wheres = %w[a b c]
|
|
21
|
+
array = [statement1, statement2]
|
|
22
|
+
assert_equal 1, array.uniq.size
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'is not equal with different ivars' do
|
|
26
|
+
statement1 = Arel::Nodes::DeleteStatement.new
|
|
27
|
+
statement1.wheres = %w[a b c]
|
|
28
|
+
statement2 = Arel::Nodes::DeleteStatement.new
|
|
29
|
+
statement2.wheres = %w[1 2 3]
|
|
30
|
+
array = [statement1, statement2]
|
|
31
|
+
assert_equal 2, array.uniq.size
|
|
32
|
+
end
|
|
33
|
+
end
|
|
14
34
|
end
|
|
@@ -29,6 +29,16 @@ module Arel
|
|
|
29
29
|
descending = Descending.new 'zomg'
|
|
30
30
|
assert descending.descending?
|
|
31
31
|
end
|
|
32
|
+
|
|
33
|
+
def test_equality_with_same_ivars
|
|
34
|
+
array = [Descending.new('zomg'), Descending.new('zomg')]
|
|
35
|
+
assert_equal 1, array.uniq.size
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_inequality_with_different_ivars
|
|
39
|
+
array = [Descending.new('zomg'), Descending.new('zomg!')]
|
|
40
|
+
assert_equal 2, array.uniq.size
|
|
41
|
+
end
|
|
32
42
|
end
|
|
33
43
|
end
|
|
34
44
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'helper'
|
|
2
|
+
|
|
3
|
+
module Arel
|
|
4
|
+
module Nodes
|
|
5
|
+
describe 'Distinct' do
|
|
6
|
+
describe 'equality' do
|
|
7
|
+
it 'is equal to other distinct nodes' do
|
|
8
|
+
array = [Distinct.new, Distinct.new]
|
|
9
|
+
assert_equal 1, array.uniq.size
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'is not equal with other nodes' do
|
|
13
|
+
array = [Distinct.new, Node.new]
|
|
14
|
+
assert_equal 2, array.uniq.size
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
data/test/nodes/test_equality.rb
CHANGED
|
@@ -69,6 +69,16 @@ module Arel
|
|
|
69
69
|
node.right.must_equal right
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
|
+
|
|
73
|
+
it 'is equal with equal ivars' do
|
|
74
|
+
array = [Equality.new('foo', 'bar'), Equality.new('foo', 'bar')]
|
|
75
|
+
assert_equal 1, array.uniq.size
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'is not equal with different ivars' do
|
|
79
|
+
array = [Equality.new('foo', 'bar'), Equality.new('foo', 'baz')]
|
|
80
|
+
assert_equal 2, array.uniq.size
|
|
81
|
+
end
|
|
72
82
|
end
|
|
73
83
|
end
|
|
74
84
|
end
|