This project is archived and is in readonly mode.
limit is ignored with has_and_belongs_to_many and count
Reported by ReggieB | February 14th, 2011 @ 09:04 AM
It's easiest to use an example to explain the problem:
class Articles
has_and_belongs_to_many categories
end
class Category
has_and_belongs_to_many articles
end
c = Category.first
c.articles.count
=> 8 # Correct
c.articles.limit(3).count
=> 8 # Incorrect
c.articles.find(:all, :limit => '3').count
=> 3 # Correct
The problem is that "LIMIT 3" is appended to the end of the SQL statement joining the two tables in the SQL generated by count:
SELECT COUNT(*) AS count_id FROM `articles` INNER JOIN
`articles_categories` ON `articles`.id =
`articles_categories`.article_id WHERE
(`articles_categories`.category_id = 9 ) LIMIT 3
As an example of a possible solution, this returns the correct
count:
SELECT count() FROM ( SELECT FROMarticles INNER JOINarticles_categoriesONarticles.id =articles_categories.article_id WHERE (articles_categories.category_id = 9 ) LIMIT 6, 4) inner_table
My system is Windows 7 with a MySQL 5.1 database
Comments and changes to this ticket
-

ReggieB February 14th, 2011 @ 09:11 AM
The last SQL is:
SELECT count(*) FROM ( SELECT * FROM `articles` INNER JOIN `articles_categories` ON `articles`.id = `articles_categories`.article_id WHERE (`articles_categories`.category_id = 9 ) LIMIT 6, 4) inner_tableFor some reason the two * in the first two lines aren't appearing above
-

Jeff Kreeftmeijer February 14th, 2011 @ 06:18 PM
- Tag set to activerecord
- Importance changed from to Low
This doesn't seem like a Rails problem, this is MySQL behavior:
mysql> select count(*) from categories; +----------+ | count(*) | +----------+ | 13 | +----------+ 1 row in set (0.00 sec) mysql> select count(*) from categories limit 3; +----------+ | count(*) | +----------+ | 13 | +----------+ 1 row in set (0.00 sec)I don't think Rails should try to "fix" this by doing creepy sub query stuff like this, but I'm wondering what the rest thinks. Maybe we can find a nicer solution?
Thanks for reporting, Reggie. :)
-

ReggieB February 15th, 2011 @ 11:26 AM
Jeff,
The problem does occur within a simpler SQL query. However, it only seems to become an ActiveRecord issue if there is a join involved. For example
Article.count => 10 # Correct
Article.limit(3).count => 3 # Also correct.The SQL generated by this statement is:
SELECT COUNT(*) AS count_id FROM (SELECT 1 FROM `categories` LIMIT 3) AS subquerySo Rails is already using the sub-query technique for simpler relationships.
The LIMIT clause acts to limit the number of lines being output. As a simple count only has one output line, LIMIT appears to have no effect. However, compare the output from these three statements:
SELECT count(*) FROM categories LIMIT 3 SELECT count(*) FROM categories GROUP BY id SELECT count(*) FROM categories GROUP BY id LIMIT 3 -

x37v February 15th, 2011 @ 11:57 PM
I've attached a diff which contains a test i added to the active record tests. This diff is from 3-0-stable
but basically:
X.join(:y).where(condition).limit(2).count != X.find_by_sql(X.join(:y).where(condition).limit(2).to_sql).count
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>