diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/arel/nodes/select_statement.rb | 3 | ||||
-rw-r--r-- | lib/arel/visitors/postgresql.rb | 27 |
2 files changed, 29 insertions, 1 deletions
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 @@ module Arel 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 |