This project is archived and is in readonly mode.

#2918 ✓resolved
qoobaa

ActiveRecord::Base finders select merging

Reported by qoobaa | July 16th, 2009 @ 07:22 PM | in 3.x

Patch allows to join multiple scopes with :select attribute instead of overwriting it:

Developer.with_scope(:find => { :select => "DISTINCT id" }) do
  Developer.with_scope(:find => { :select => "DISTINCT salary" }) do
    Developer.find(:first).salary
  end
end

Will generate SQL like:
SELECT DISTINCT id,salary ON ...

Instead of:
SELECT DISTINCT salary ON ...

It's quite important when you add aggregate functions or GROUP in your scopes.

EDIT: this is duplicate of #1295, but my patch fixes also problems with DISTINCTs

Comments and changes to this ticket

  • Jeremy Kemper

    Jeremy Kemper May 4th, 2010 @ 06:48 PM

    • Milestone changed from 2.x to 3.x
  • Blane Dabney

    Blane Dabney May 5th, 2010 @ 09:42 PM

    I've attached a patch without tests as an example fix that only covers the basic case of chaining select calls (i.e. Topic.select(:id).select(:name)). There are a few issues surrounding it that may require discussion before implementing. Once I get some feedback I'll submit a full patch with tests.

    The first issue is DISTINCTs. I think these really fall outside of the scope of this method (select) and should probably be handled with a new method or possibly two to properly handle DISTINCT ON. Adding a distinct method would just need an instance variable to capture the set state when its called so that the DISTINCT keyword can be prepended to the first @select_values element when build_arel gets called. DISTINCT ON is more complex, as some (all?) SQL implementations require the leftmost ORDER BY expressions to match the DISTINCT ON expressions.

    The second issue is merge/&. Currently, the instance variables backing all multi-value methods except @join_values and @where_values are overwritten during a merge. I don't see why @select_values, @group_values and @order_values can't simply be appended, and @having_values handled like @where_values.

    The third issue (non-issue) is handling this properly when raw SQL fragments are used. I'd say not handling it is the appropriate action to take here, but I thought I'd toss that out for consideration.

  • Blane Dabney

    Blane Dabney May 5th, 2010 @ 09:45 PM

    Having issues attaching the patch. It's short, so here it is:

    .../lib/active_record/relation/query_methods.rb | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)

    diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
    index 7bca12d..89edd1e 100644
    --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -175,10 +175,11 @@ module ActiveRecord

       quoted_table_name = @klass.quoted_table_name
    
       if selects.present?
    
    •  selects.each do |s|
      
    •  selects.reject! do |s|
         @implicit_readonly = false
      
    •    arel = arel.project(s) if s.present?
      
    •    !s.present?
       end
      
    •  arel = arel.project(selects)
      
      else
       arel = arel.project(quoted_table_name + '.*')
      
      end
  • Blane Dabney

    Blane Dabney May 5th, 2010 @ 09:49 PM

     .../lib/active_record/relation/query_methods.rb    |    5 +++--
     1 files changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
    index 7bca12d..89edd1e 100644
    --- a/activerecord/lib/active_record/relation/query_methods.rb
    +++ b/activerecord/lib/active_record/relation/query_methods.rb
    @@ -175,10 +175,11 @@ module ActiveRecord
           quoted_table_name = @klass.quoted_table_name
     
           if selects.present?
    -        selects.each do |s|
    +        selects.reject! do |s|
               @implicit_readonly = false
    -          arel = arel.project(s) if s.present?
    +          !s.present?
             end
    +        arel = arel.project(selects)
           else
             arel = arel.project(quoted_table_name + '.*')
           end
    
  • Rohit Arondekar

    Rohit Arondekar July 9th, 2010 @ 03:13 AM

    • State changed from “new” to “resolved”
    • Importance changed from “” to “”

    Multiple selects are now merged in Rails master. Ticket 4841 and Commit http://github.com/rails/rails/commit/0ebb5bf6590b8ac62c53538ade7095... for reference.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Referenced by

Pages