Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Make unions chainable.

  • Loading branch information...
commit 31da1e0c23ef33e505ef6c1d2d6a427597a0e272 1 parent 7373e81
Jonathan Roes authored
2  lib/arel/nodes/binary.rb
View
@@ -29,8 +29,6 @@ def initialize_copy other
NotEqual
NotIn
Or
- Union
- UnionAll
Intersect
Except
}.each do |name|
4 lib/arel/nodes/select_statement.rb
View
@@ -2,11 +2,12 @@ module Arel
module Nodes
class SelectStatement < Arel::Nodes::Node
attr_reader :cores
- attr_accessor :limit, :orders, :lock, :offset, :with
+ attr_accessor :limit, :unions, :orders, :lock, :offset, :with
def initialize cores = [SelectCore.new]
#puts caller
@cores = cores
+ @unions = []
@orders = []
@limit = nil
@lock = nil
@@ -17,6 +18,7 @@ def initialize cores = [SelectCore.new]
def initialize_copy other
super
@cores = @cores.map { |x| x.clone }
+ @unions = @unions.map { |x| x.clone }
@orders = @orders.map { |x| x.clone }
end
end
6 lib/arel/nodes/unary.rb
View
@@ -11,17 +11,19 @@ def initialize expr
%w{
Bin
+ DistinctOn
Group
Grouping
Having
Limit
+ Lock
Not
Offset
On
Ordering
Top
- Lock
- DistinctOn
+ Union
+ UnionAll
}.each do |name|
const_set(name, Class.new(Unary))
end
3  lib/arel/select_manager.rb
View
@@ -185,7 +185,8 @@ def union operation, other = nil
node_class = Nodes::Union
end
- node_class.new self.ast, other.ast
+ @ast.unions << node_class.new(other.ast)
+ self
end
def intersect other
12 lib/arel/visitors/to_sql.rb
View
@@ -119,6 +119,7 @@ def visit_Arel_Nodes_SelectStatement o
[
(visit(o.with) if o.with),
o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
+ (o.unions.map { |x| visit_Arel_Nodes_Union x }.join ' ' unless o.unions.empty?),
("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
(visit(o.limit) if o.limit),
(visit(o.offset) if o.offset),
@@ -161,11 +162,12 @@ def visit_Arel_Nodes_WithRecursive o
end
def visit_Arel_Nodes_Union o
- "( #{visit o.left} UNION #{visit o.right} )"
- end
-
- def visit_Arel_Nodes_UnionAll o
- "( #{visit o.left} UNION ALL #{visit o.right} )"
+ # FIXME remove is_a?
+ if o.is_a? Nodes::Union
+ "UNION #{visit o.expr}"
+ else
+ "UNION ALL #{visit o.expr}"
+ end
end
def visit_Arel_Nodes_Intersect o
27 test/test_select_manager.rb
View
@@ -296,17 +296,24 @@ def test_join_sources
@m2.project Arel.star
@m2.where(table[:age].gt(99))
-
+ @m3 = Arel::SelectManager.new Table.engine, table
+ @m3.project Arel.star
+ @m3.where(table[:id].gt(0))
end
it 'should union two managers' do
- # FIXME should this union "managers" or "statements" ?
- # FIXME this probably shouldn't return a node
- node = @m1.union @m2
+ statement = @m1.union @m2
- # maybe FIXME: decide when wrapper parens are needed
- node.to_sql.must_be_like %{
- ( SELECT * FROM "users" WHERE "users"."age" < 18 UNION SELECT * FROM "users" WHERE "users"."age" > 99 )
+ statement.to_sql.must_be_like %{
+ SELECT * FROM "users" WHERE "users"."age" < 18 UNION SELECT * FROM "users" WHERE "users"."age" > 99
+ }
+ end
+
+ it 'should be chainable' do
+ statement = @m1.union(@m2).union(@m3)
+
+ statement.to_sql.must_be_like %{
+ SELECT * FROM "users" WHERE "users"."age" < 18 UNION SELECT * FROM "users" WHERE "users"."age" > 99 UNION SELECT * FROM "users" WHERE "users"."id" > 0
}
end
@@ -314,7 +321,7 @@ def test_join_sources
node = @m1.union :all, @m2
node.to_sql.must_be_like %{
- ( SELECT * FROM "users" WHERE "users"."age" < 18 UNION ALL SELECT * FROM "users" WHERE "users"."age" > 99 )
+ SELECT * FROM "users" WHERE "users"."age" < 18 UNION ALL SELECT * FROM "users" WHERE "users"."age" > 99
}
end
@@ -392,7 +399,9 @@ def test_join_sources
union = recursive_term.union(non_recursive_term)
- as_statement = Arel::Nodes::As.new replies, union
+ # TODO I think 'as' should do the parens here. A union doesn't
+ # need surrounding parens
+ as_statement = Arel::Nodes::As.new replies, union.ast
manager = Arel::SelectManager.new Table.engine
manager.with(:recursive, as_statement).from(replies).project(Arel.star)
19 test/visitors/test_mysql.rb
View
@@ -7,15 +7,16 @@ module Visitors
@visitor = MySQL.new Table.engine.connection
end
- it 'squashes parenthesis on multiple unions' do
- subnode = Nodes::Union.new 'left', 'right'
- node = Nodes::Union.new subnode, 'topright'
- assert_equal 1, @visitor.accept(node).scan('(').length
-
- subnode = Nodes::Union.new 'left', 'right'
- node = Nodes::Union.new 'topleft', subnode
- assert_equal 1, @visitor.accept(node).scan('(').length
- end
+ # No longer needed, parens not used
+# it 'no parens for unions' do
+# subnode = Nodes::Union.new 'left', 'right'
+# node = Nodes::Union.new subnode, 'topright'
+# assert_equal 0, @visitor.accept(node).scan('(').length
+#
+# subnode = Nodes::Union.new 'left', 'right'
+# node = Nodes::Union.new 'topleft', subnode
+# assert_equal 0, @visitor.accept(node).scan('(').length
+# end
###
# :'(
Please sign in to comment.
Something went wrong with that request. Please try again.