-
Notifications
You must be signed in to change notification settings - Fork 864
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
count(*) problem with postgres. #45
Comments
Thanks for detail analysis for this issue. I knew about it before, but I needed someone to dissect it for me. Also, I never really had the motivation to fix it inside will_paginate since it's clearly an ActiveRecord issue. Putting too much assumptions about SQL inside will_paginate is not where I want to go. Can you check how ActiveRecord 3.0 handles these cases? Because it's built on Arel now, so it must understand relational logic better. I'm interested if it's possible to build a scope with "distinct" (like here) and then call count and perform a limited find all without any special parameters or workarounds. |
I can comment on this and potentially offer a patch (or the start of a patch). I had this same issue with Microsoft's SQL Server (yea, yea, I know, but I have to for work). As junaid pointed out, will_paginate re-writes the query for MySQL so that it becomes DISTINCT(table_name.id). It doesn't do that for other databases and I think I found the issue. MySQL uses the backtick ( This was easily fixed (for SQL Server) by changing the gsub to a regexp including "[" and "]" as well as the backtick (so it's now if EDIT: please ignore the backslash before the backtick in the gsub in the last code snippet. If I remove the backslash, it ends code mode at that backtick, but the backslash should be thought of as an escape character there. I'm not completely sure what's going on, but the square brackets need a backslash before them in the regexp, but the backtick shouldn't have one before it. |
I'm really dying here of need for a proper, tested patch … You guys did great investigative work, that could maybe continue in form of a pull request? ;) Maybe? |
I think 470dae1 fixes this one too |
thanks kjg, i will check this and update this ticket. |
this issue looks quite old, but seems to still exist Table1.joins("LEFT OUTER JOIN table2 ON ...").paginate(:page => @params[:page]) so the pagination is coming up with more records than my DISTINCT query does, the fix from kjg looked like it should do what I want, but the code base no longer has a finder.rb file, I guess I'll take a look at lib/will_paginate/active_record.rb |
just came up with a dirty workaround, might help someone else
the problem does not exist in paginate_by_sql |
Maybe something like this will help?: "select count(*) from (#{collection.to_sql}) count_sql" |
house9 -- many thanks, this solved it (at least until a real fix is in place -- I suspect this is going to get pokey on large datasets). |
@mislav would you accept a pull request for this? https://github.com/mislav/will_paginate/blob/master/lib/will_paginate/active_record.rb#L67 rel = rel.apply_finder_options(@wp_count_options) if defined? @wp_count_options
rel.count i believe |
Bump |
This plugin don't works with postgres for some queries that have distinct and selecting more than one column because Postgres follow sql standard strictly and mysql added few things in sql. If you change the count query using subquery then it will work fine for both of them mysql and postgers. Now plugin do following things in case of mysql and postgres.Here is example.
Mysql ::
Regular query ::
SELECT DISTINCT
tenders
.* FROMtenders
INNER JOINassignments
ONtenders
.id =assignments
.assignable_id ANDassignments
.assignable_type = 'Tender'Count query ::
SELECT count(DISTINCT tenders.id) AS count_distinct_tenders_id FROM
tenders
INNER JOINassignments
ONtenders
.id =assignments
.assignable_id ANDassignments
.assignable_type = 'Tender'Postgres ::
Regular query ::
SELECT DISTINCT "tenders".* FROM "tenders" INNER JOIN "assignments" ON "tenders".id = "assignments".assignable_id AND "assignments".assignable_type = E'Tender'
Count query ::
SELECT count(DISTINCT "tenders".*) AS count_distinct_tenders_all FROM "tenders" INNER JOIN "assignments" ON "tenders".id = "assignments".assignable_id AND "assignments".assignable_type = E'Tender'
This count query of postgres gives following error "PGError: ERROR: could not identify an equality operator for type tenders". As per postgres documentation you can only give one expression to count function which is sql standard but mysql allows more than one expressions in count(*) function. If you transform this query using this then it will work for both.
SELECT count() from(
SELECT DISTINCT "tenders". FROM "tenders" INNER JOIN "assignments" ON "tenders".id = "assignments".assignable_id AND "assignments".assignable_type = E'Tender' ) as temp
I also tried new count query way with sqlite and it worked so we are safe to implement for sqlite,mysql and postgres.
Thanks
Junaid.
The text was updated successfully, but these errors were encountered: