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.
Files changed (70) hide show
  1. data/.travis.yml +2 -4
  2. data/Gemfile +2 -2
  3. data/History.txt +3 -54
  4. data/Manifest.txt +8 -2
  5. data/README.markdown +8 -4
  6. data/Rakefile +1 -1
  7. data/arel.gemspec +21 -29
  8. data/lib/arel/crud.rb +3 -3
  9. data/lib/arel/nodes/and.rb +10 -0
  10. data/lib/arel/nodes/binary.rb +11 -0
  11. data/lib/arel/nodes/extract.rb +11 -0
  12. data/lib/arel/nodes/false.rb +7 -0
  13. data/lib/arel/nodes/function.rb +11 -0
  14. data/lib/arel/nodes/grouping.rb +7 -0
  15. data/lib/arel/nodes/insert_statement.rb +12 -0
  16. data/lib/arel/nodes/named_function.rb +9 -0
  17. data/lib/arel/nodes/select_core.rb +20 -0
  18. data/lib/arel/nodes/select_statement.rb +15 -1
  19. data/lib/arel/nodes/table_alias.rb +4 -0
  20. data/lib/arel/nodes/terminal.rb +7 -0
  21. data/lib/arel/nodes/true.rb +7 -0
  22. data/lib/arel/nodes/unary.rb +10 -1
  23. data/lib/arel/nodes/update_statement.rb +15 -0
  24. data/lib/arel/nodes/window.rb +30 -3
  25. data/lib/arel/nodes.rb +1 -0
  26. data/lib/arel/predications.rb +18 -2
  27. data/lib/arel/select_manager.rb +6 -2
  28. data/lib/arel/table.rb +14 -1
  29. data/lib/arel/tree_manager.rb +0 -2
  30. data/lib/arel/visitors/bind_visitor.rb +10 -0
  31. data/lib/arel/visitors/dot.rb +2 -2
  32. data/lib/arel/visitors/to_sql.rb +142 -31
  33. data/lib/arel.rb +1 -3
  34. data/test/nodes/test_and.rb +20 -0
  35. data/test/nodes/test_as.rb +12 -0
  36. data/test/nodes/test_ascending.rb +10 -0
  37. data/test/nodes/test_bin.rb +10 -0
  38. data/test/nodes/test_count.rb +12 -0
  39. data/test/nodes/test_delete_statement.rb +20 -0
  40. data/test/nodes/test_descending.rb +10 -0
  41. data/test/nodes/test_distinct.rb +20 -0
  42. data/test/nodes/test_equality.rb +10 -0
  43. data/test/nodes/test_extract.rb +14 -0
  44. data/test/nodes/test_false.rb +20 -0
  45. data/test/nodes/test_grouping.rb +25 -0
  46. data/test/nodes/test_infix_operation.rb +10 -0
  47. data/test/nodes/test_insert_statement.rb +24 -0
  48. data/test/nodes/test_named_function.rb +16 -0
  49. data/test/nodes/test_not.rb +12 -0
  50. data/test/nodes/test_or.rb +12 -0
  51. data/test/nodes/test_over.rb +18 -0
  52. data/test/nodes/test_select_core.rb +38 -0
  53. data/test/nodes/test_select_statement.rb +36 -0
  54. data/test/nodes/test_sql_literal.rb +10 -0
  55. data/test/nodes/test_sum.rb +12 -0
  56. data/test/nodes/test_table_alias.rb +36 -0
  57. data/test/nodes/test_true.rb +21 -0
  58. data/test/nodes/test_update_statement.rb +40 -0
  59. data/test/nodes/test_window.rb +73 -0
  60. data/test/support/fake_record.rb +5 -1
  61. data/test/test_attributes.rb +12 -0
  62. data/test/test_insert_manager.rb +0 -2
  63. data/test/test_select_manager.rb +10 -5
  64. data/test/test_table.rb +24 -0
  65. data/test/test_update_manager.rb +8 -0
  66. data/test/visitors/test_bind_visitor.rb +20 -1
  67. data/test/visitors/test_to_sql.rb +78 -0
  68. metadata +84 -82
  69. data/lib/arel/nodes/ordering.rb +0 -6
  70. data/lib/arel/relation.rb +0 -6
@@ -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 < Arel::Nodes::Node; end
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
@@ -13,6 +13,7 @@ require 'arel/nodes/false'
13
13
 
14
14
  # unary
15
15
  require 'arel/nodes/unary'
16
+ require 'arel/nodes/grouping'
16
17
  require 'arel/nodes/ascending'
17
18
  require 'arel/nodes/descending'
18
19
  require 'arel/nodes/unqualified_column'
@@ -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.exclude_end?
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.exclude_end?
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
@@ -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 ARel 4.0.0 with no replacement"
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 ARel 4.0.0. Please
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 ARel 4.0.0
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
@@ -1,7 +1,5 @@
1
1
  module Arel
2
2
  class TreeManager
3
- # FIXME: Remove this.
4
- include Arel::Relation
5
3
  include Arel::FactoryMethods
6
4
 
7
5
  attr_reader :ast, :engine
@@ -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
@@ -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 \"ARel\" {\nnode [width=0.375,height=0.25,shape=record];\n" +
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
 
@@ -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 ' AND '}" unless o.wheres.empty?)
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 ARel 4.0.0. Please set the primary
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[table][name]
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
- (visit(o.with) if o.with),
121
- o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
122
- ("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
123
- (visit(o.limit) if o.limit),
124
- (visit(o.offset) if o.offset),
125
- (visit(o.lock) if o.lock),
126
- ].compact.join ' '
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
- "SELECT",
132
- (visit(o.top) if o.top),
133
- (visit(o.set_quantifier) if o.set_quantifier),
134
- ("#{o.projections.map { |x| visit x }.join ', '}" unless o.projections.empty?),
135
- ("FROM #{visit(o.source)}" if o.source && !o.source.empty?),
136
- ("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
137
- ("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
138
- (visit(o.having) if o.having),
139
- ("WINDOW #{o.windows.map { |x| visit x }.join ', ' }" unless o.windows.empty?)
140
- ].compact.join ' '
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
- 'DISTINCT'
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} #{visit o.right if o.right}"
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.empty? ? 'NULL' : o.map { |x| visit x }.join(', ')
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 = '3.0.3'
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
+
@@ -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
@@ -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
@@ -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
+
@@ -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