Permalink
Browse files

adding Distinct ON node

  • Loading branch information...
tenderlove committed Apr 21, 2011
1 parent cae83ce commit 0b9af9762a5f3431f83a9bba6919fef9346e310a
@@ -5,6 +5,10 @@
require 'arel/nodes/insert_statement'
require 'arel/nodes/update_statement'
# terminal
require 'arel/nodes/terminal'
# unary
require 'arel/nodes/unary'
require 'arel/nodes/unqualified_column'
@@ -0,0 +1,6 @@
module Arel
module Nodes
class Distinct < Arel::Nodes::Node
end
end
end
@@ -20,14 +20,9 @@ def initialize expr
On
Top
Lock
DistinctOn
}.each do |name|
const_set(name, Class.new(Unary))
end
class Distinct < Unary
def initialize expr = nil
super
end
end
end
end
@@ -6,25 +6,6 @@ def visit_Arel_Nodes_Lock o
visit o.expr
end
def visit_Arel_Nodes_SelectStatement o
if !o.orders.empty? && using_distinct_on?(o)
subquery = o.dup
subquery.orders = []
subquery.limit = nil
subquery.offset = nil
sql = super(subquery)
[
"SELECT * FROM (#{sql}) AS id_list",
"ORDER BY #{aliased_orders(o.orders).join(', ')}",
(visit(o.limit) if o.limit),
(visit(o.offset) if o.offset),
].compact.join ' '
else
super
end
end
def visit_Arel_Nodes_Matches o
"#{visit o.left} ILIKE #{visit o.right}"
end
@@ -33,12 +14,8 @@ def visit_Arel_Nodes_DoesNotMatch o
"#{visit o.left} NOT ILIKE #{visit o.right}"
end
def using_distinct_on?(o)
o.cores.any? do |core|
core.projections.any? do |projection|
/DISTINCT ON/ === projection
end
end
def visit_Arel_Nodes_DistinctOn o
"DISTINCT ON ( #{visit o.expr} )"
end
def aliased_orders orders
@@ -126,8 +126,8 @@ def visit_Arel_Nodes_SelectCore o
"SELECT",
(visit(o.top) if o.top),
(visit(o.set_quantifier) if o.set_quantifier),
"#{o.projections.map { |x| visit x }.join ', '}",
visit(o.source),
("#{o.projections.map { |x| visit x }.join ', '}" unless o.projections.empty?),
(visit(o.source) if o.source),
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
(visit(o.having) if o.having),
@@ -54,7 +54,7 @@ def execute sql, name = nil, *args
def test_join_sources
manager = Arel::SelectManager.new Table.engine
manager.join_sources << Arel::Nodes::StringJoin.new('foo')
assert_equal "SELECT FROM 'foo'", manager.to_sql
assert_equal "SELECT FROM 'foo'", manager.to_sql
end
describe 'backwards compatibility' do
@@ -101,7 +101,7 @@ module Visitors
sql.must_be_like %{
SELECT * FROM (
SELECT raw_sql_.*, rownum raw_rnum_
FROM (SELECT ) raw_sql_
FROM (SELECT) raw_sql_
WHERE rownum <= 20
)
WHERE raw_rnum_ > 10
@@ -126,7 +126,7 @@ module Visitors
sql.must_be_like %{
SELECT * FROM (
SELECT raw_sql_.*, rownum raw_rnum_
FROM (SELECT ) raw_sql_
FROM (SELECT) raw_sql_
)
WHERE raw_rnum_ > 10
}
@@ -32,6 +32,17 @@ module Visitors
assert_equal 1, sql.scan(/LIMIT/).length, 'should have one limit'
end
it 'should support DISTINCT ON' do
core = Arel::Nodes::SelectCore.new
core.set_quantifier = Arel::Nodes::DistinctOn.new(Arel.sql('aaron'))
assert_match 'DISTINCT ON ( aaron )', @visitor.accept(core)
end
it 'should support DISTINCT' do
core = Arel::Nodes::SelectCore.new
core.set_quantifier = Arel::Nodes::Distinct.new
assert_equal 'SELECT DISTINCT', @visitor.accept(core)
end
end
end
end

0 comments on commit 0b9af97

Please sign in to comment.