From 9e9e5906754abfb168faba7d265719b5e613624f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 23 Sep 2010 13:07:48 -0700 Subject: [PATCH] adding a select statment visitor --- lib/arel/nodes/select_statement.rb | 3 ++- lib/arel/visitors/postgresql.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/arel/nodes/select_statement.rb b/lib/arel/nodes/select_statement.rb index 637ba5d1d0..371fd7bf21 100644 --- a/lib/arel/nodes/select_statement.rb +++ b/lib/arel/nodes/select_statement.rb @@ -14,7 +14,8 @@ def initialize cores = [SelectCore.new] def initialize_copy other super - @cores = @cores.map { |x| x.clone } + @cores = @cores.map { |x| x.clone } + @orders = @orders.map { |x| x.clone } end end end diff --git a/lib/arel/visitors/postgresql.rb b/lib/arel/visitors/postgresql.rb index 93535f4488..5f0b23a11e 100644 --- a/lib/arel/visitors/postgresql.rb +++ b/lib/arel/visitors/postgresql.rb @@ -1,6 +1,33 @@ module Arel module Visitors class PostgreSQL < Arel::Visitors::ToSql + private + 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 #{o.orders.map { |x| visit x }.join(', ')}", + ("LIMIT #{o.limit}" if o.limit), + (visit(o.offset) if o.offset), + ].compact.join ' ' + else + super + end + end + + def using_distinct_on?(o) + o.cores.any? do |core| + core.projections.any? do |projection| + /DISTINCT ON/ === projection + end + end + end end end end -- GitLab