Skip to content
This repository

Eager loading with 'includes' overrides 'select' in SQL query #2303

Closed
wants to merge 1 commit into from

9 participants

Dieter Komendera Thomas Dippel the8472 Isaac Sanders Steve Klabnik Joe Van Dyk Tomasz Pajor Jyr Gaxiola Frankovskyi Bogdan
Dieter Komendera
kommen commented July 27, 2011

When creating a query with select and includes like

Post.select('author_id, COUNT(author_id) AS num_posts, authors.*').group('author_id').includes(:author)

the select part is ignored when querying the database.

However, if to_sql is called on the Relation, the query gets constructed directly.

to_sql output:

SELECT author_id, COUNT(author_id) AS num_posts, authors.* FROM "posts"  GROUP BY author_id

query sent to the db:

SELECT "posts"."id" AS t0_r0, "posts"."author_id" AS t0_r1, "posts"."title" AS t0_r2, "posts"."body" AS t0_r3, "posts"."type" AS t0_r4, "posts"."comments_count" AS t0_r5, "posts"."taggings_count" AS t0_r6, "posts"."taggings_with_delete_all_count" AS t0_r7, "posts"."taggings_with_destroy_count" AS t0_r8, "posts"."tags_count" AS t0_r9, "posts"."tags_with_destroy_count" AS t0_r10, "posts"."tags_with_nullify_count" AS t0_r11, "authors"."id" AS t1_r0, "authors"."name" AS t1_r1, "authors"."author_address_id" AS t1_r2, "authors"."author_address_extra_id" AS t1_r3, "authors"."organization_id" AS t1_r4, "authors"."owned_essay_id" AS t1_r5 FROM "posts" LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id" GROUP BY author_id

See the attached patch for a complete testcase which currently fails.

Thomas Dippel

+1

the8472

Wouldn'g using preload instead of includes suffice in most cases?

Isaac Sanders

This seems similar to #6132.

Steve Klabnik
Collaborator

As a note, this no longer merges cleanly, so a rebase will be needed.

Joe Van Dyk

Man, I'd love to see this fixed. So confusing to have #to_sql output something, but the query that runs is completely different.

Tomasz Pajor

Had a similar problem lately, wanted to run something like this:

select(s).joins(:rule, :campaign => :customer).joins(j).includes(:rule, :campaign, :customer).where(w.join(' AND ')).having(h.join(' AND ')).order('rule_resource.priority ASC').all

https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/relation/finder_methods.rb#L230

You need to replace

relation = except(:includes, :eager_load, :preload, :select).select(join_dependency.columns)

with

relation = except(:includes, :eager_load, :preload).select(join_dependency.columns)

Can anybody point out why there is a select there in the first place?
If it's there for a reason then having will never work in my case.

Steve Klabnik
Collaborator

@kommen I mentioned 6 months ago that this needed rebased, are you still interested in following-up with this pull request?

Dieter Komendera

@steveklabnik Thanks for the reminder. I've rebased the commit onto the 3-1-stable branch. If you want me to open another pull request for 3-2-stable or master, let me know.

Steve Klabnik
Collaborator

Oh! yes, 3-1-stable isn't getting any non-security fixes these days. The way we prefer it to is to open a pull against master, and then fixes get backported as necessary. So can you please re-submit against master? Thanks!

Steve Klabnik steveklabnik closed this November 18, 2012
Dieter Komendera kommen referenced this pull request from a commit in kommen/rails November 18, 2012
Dieter Komendera Add test to ensure preloading works as expected with "select" and "in…
…cludes".

This didn't work in rails 3.1. See #2303 for more information and original pull request.
22ed92d
Dieter Komendera

@steveklabnik Turns out, this is fixed in 3.2 and also master. I've rebased onto master anyway, just in case: #8258

Jyr Gaxiola
jyr commented March 01, 2013

This was added in 3.2.12? I fail to override the select

Jyr Gaxiola
jyr commented March 01, 2013

I have same problem, @the8472 can you show me a example using preload?

I'm use

Property.group("bla").where("bla").select("DISTINCT ON(table.created_at) table.id, *").includes(bla)

the8472
Property.group("bla").where("bla").select("DISTINCT ON(table.created_at) table.id, *").joins(:bla).preload(:bla)
Frankovskyi Bogdan

I have the same issue in 3.2.12.

Dish.select("dishes.*, ordered_dishes.id as dish_ordered").
includes(:ordered_dishes, :ordered_dishes => :user_menu).
where("dishes.menu_section_id in (?) AND (user_menus.user_id = ? OR user_menus.user_id IS NULL)", menu_section_ids, user_id).

Result:

SELECT "dishes"."id" AS t0_r0, "dishes"."title" AS t0_r1, "dishes"."created_at" AS t0_r2, "dishes"."updated_at" AS t0_r3, "dishes"."menu_section_id" AS t0_r4, "ordered_dishes"."id" AS t1_r0, "ordered_dishes"."user_menu_id" AS t1_r1, "ordered_dishes"."dish_id" AS t1_r2, "ordered_dishes"."created_at" AS t1_r3, "ordered_dishes"."updated_at" AS t1_r4, "user_menus"."id" AS t2_r0, "user_menus"."weekly_menu_id" AS t2_r1, "user_menus"."user_id" AS t2_r2, "user_menus"."created_at" AS t2_r3, "user_menus"."updated_at" AS t2_r4, "user_menus"."ordered" AS t2_r5 FROM "dishes"
LEFT OUTER JOIN "ordered_dishes" ON "ordered_dishes"."dish_id" = "dishes"."id"
LEFT OUTER JOIN "user_menus" ON "user_menus"."id" = "ordered_dishes"."user_menu_id" WHERE (dishes.menu_section_id in (16,16,16) AND (user_menus.user_id = 2 OR user_menus.user_id IS NULL))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Nov 18, 2012
Dieter Komendera Add failing test to show that `includes` overwrites `select`. a3a03dd
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 11 additions and 0 deletions. Show diff stats Hide diff stats

  1. 11  activerecord/test/cases/relations_test.rb
11  activerecord/test/cases/relations_test.rb
@@ -1013,4 +1013,15 @@ def test_update_all_with_joins_and_offset_and_order
1013 1013
     assert_equal posts(:thinking), comments(:more_greetings).post
1014 1014
     assert_equal posts(:welcome),  comments(:greetings).post
1015 1015
   end
  1016
+
  1017
+  def test_eager_loading_with_includes_and_select
  1018
+    scope = Post.select('author_id, COUNT(author_id) AS num_posts, authors.*').group('author_id').includes(:author)
  1019
+    result = scope.map do |post|
  1020
+      [post.num_posts, post.author.name]
  1021
+    end
  1022
+
  1023
+    expected = [[5, "David"], [3, "Mary"], [2, "Bob"]]
  1024
+    assert_equal expected, result
  1025
+    assert scope.eager_loading?, "should eager load authors"
  1026
+  end
1016 1027
 end
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.